Merge remote-tracking branch 'upstream/develop' into hughns/msc3824-oidc-aware

This commit is contained in:
Hugh Nimmo-Smith 2023-01-05 17:03:20 +00:00
commit bfed447b21
2820 changed files with 74906 additions and 21846 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text
**/src/androidTest/assets/*.realm filter=lfs diff=lfs merge=lfs -text

View file

@ -5,7 +5,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Thank you for taking the time to propose a new feature or make a suggestion. Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/vector-im/element-meta/discussions/new?category=ideas).
- type: textarea - type: textarea
id: usecase id: usecase
attributes: attributes:

View file

@ -10,7 +10,6 @@ body:
id: checklist id: checklist
attributes: attributes:
label: Release checklist label: Release checklist
description: For the template example, we are releasing the version 1.2.3. Replace 1.2.3 with the version in the issue body.
placeholder: | placeholder: |
If you are reading this, you have deleted the content of the release template: undo the deletion or start again. If you are reading this, you have deleted the content of the release template: undo the deletion or start again.
value: | value: |
@ -20,32 +19,11 @@ body:
- [ ] 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. - [ ] 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.
- [ ] While Weblate is locked, and after the PR from Weblate has been merged, handle all the TODOs in the main `strings.xml` file - [ ] While Weblate is locked, and after the PR from Weblate has been merged, handle all the TODOs in the main `strings.xml` file
- [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect. - [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
- [ ] Ensure all [the required PRs](https://github.com/vector-im/element-android/pulls?q=is%3Aopen+is%3Apr+label%3AZ-NextRelease) have been merged
### Do the release ### Do the release
- [ ] Make sure `develop` and `main` are up to date (git pull) - [ ] Run the script ./tools/release/releaseScript.sh and follow the steps.
- [ ] Checkout develop and create a release with gitflow, branch name `release/1.2.3`
- [ ] Check the crashes from the PlayStore
- [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.2.3-dev
- [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()`
- [ ] Create an account on matrix.org and do some smoke tests that the sanity test does not cover like: 1-1 call, 1-1 video call, Jitsi call for instance
- [ ] Run towncrier: `towncrier build --version v1.2.3 --draft` (remove `--draft` do write the file CHANGES.md)
- [ ] Check that the folder `changelog.d` is empty. It can happen that some remaining files stay here
- [ ] Check the file CHANGES.md consistency. It's possible to reorder items (most important changes first) or change their section if relevant. Also an opportunity to fix some typo, or rewrite things
- [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs
- [ ] (optional) 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 (if created)
- [ ] Push `main` and the new tag `v1.2.3` to origin
- [ ] Checkout `develop`
- [ ] Increase version (versionPatch + 2) 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 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
### Once tested and validated internally ### Once tested and validated internally
@ -82,29 +60,9 @@ body:
The SDK2 and the sample app are released only when Element has been pushed to production. The SDK2 and the sample app are released only when Element has been pushed to production.
- [ ] Checkout the `main` branch on Element Android project - [ ] On the [SDK2 project](https://github.com/matrix-org/matrix-android-sdk2), run the script ./tools/releaseScript.sh and follow the instructions.
#### On the SDK2 project Note: if the step `./gradlew closeAndReleaseRepository` fails (for instance, several repositories are waiting to be handled), you have to close and release the repository manually. Do the following steps:
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
- [ ] Checkout the branch `main`
- [ ] Run the command `./gradlew publish --no-daemon --no-parallel`. You'll need some non-public element to do so
- [ ] Run the command `./gradlew closeAndReleaseRepository`. If it is working well, you can jump directly to the final step of this section.
If `./gradlew closeAndReleaseRepository` fails (for instance, several repositories are waiting to be handled), you have to close and release the repository manually. Do the following steps:
- [ ] Connect to https://s01.oss.sonatype.org - [ ] Connect to https://s01.oss.sonatype.org
- [ ] Click on Staging Repositories and check the the files have been uploaded - [ ] Click on Staging Repositories and check the the files have been uploaded
@ -112,15 +70,6 @@ body:
- [ ] Wait (check Activity tab until step "Repository closed" is displayed) - [ ] Wait (check Activity tab until step "Repository closed" is displayed)
- [ ] Click on release. The staging repository will disappear - [ ] Click on release. The staging repository will disappear
Final step
- [ ] 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 ### Android SDK2 sample
https://github.com/matrix-org/matrix-android-sdk2-sample https://github.com/matrix-org/matrix-android-sdk2-sample

View file

@ -40,7 +40,7 @@ jobs:
with: with:
name: vector-${{ matrix.target }}-debug name: vector-${{ matrix.target }}-debug
path: | path: |
vector/build/outputs/apk/*/debug/*.apk vector-app/build/outputs/apk/*/debug/*.apk
release: release:
name: Build unsigned GPlay APKs name: Build unsigned GPlay APKs
@ -65,7 +65,7 @@ jobs:
with: with:
name: vector-gplay-release-unsigned name: vector-gplay-release-unsigned
path: | path: |
vector/build/outputs/apk/*/release/*.apk vector-app/build/outputs/apk/*/release/*.apk
exodus: exodus:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View file

@ -11,8 +11,10 @@ jobs:
- run: | - run: |
npm install --save-dev @babel/plugin-transform-flow-strip-types npm install --save-dev @babel/plugin-transform-flow-strip-types
- name: Danger - name: Danger
uses: danger/danger-js@11.1.1 uses: danger/danger-js@11.2.0
with: with:
args: "--dangerfile tools/danger/dangerfile.js" args: "--dangerfile ./tools/danger/dangerfile.js"
env: env:
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
# Fallback for forks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Build docs - name: Build docs
run: ./gradlew dokkaHtml run: ./gradlew dokkaHtml

View file

@ -16,7 +16,7 @@ env:
jobs: jobs:
# More info on should-i-run: # More info on should-i-run:
# If this fails to run (the IF doesn't complete) then the needs will not be satisfied for any of the # If this fails to run (the IF doesn't complete) then the needs will not be satisfied for any of the
# other jobs below, so none will run. # other jobs below, so none will run.
# except for the notification job at the bottom which will run all the time, unless should-i-run isn't # except for the notification job at the bottom which will run all the time, unless should-i-run isn't
# successful, or all the other jobs have succeeded # successful, or all the other jobs have succeeded
@ -27,11 +27,12 @@ jobs:
if: github.event.pull_request.merged # Additionally require PR to have been completely merged. if: github.event.pull_request.merged # Additionally require PR to have been completely merged.
steps: steps:
- run: echo "Run those tests!" # no-op success - run: echo "Run those tests!" # no-op success
ui-tests: ui-tests:
name: UI Tests (Synapse) name: UI Tests (Synapse)
needs: should-i-run needs: should-i-run
runs-on: macos-latest runs-on: buildjet-4vcpu-ubuntu-2204
timeout-minutes: 90 # We might need to increase it if the time for tests grows
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -52,7 +53,7 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Start synapse server - name: Start synapse server
uses: michaelkaye/setup-matrix-synapse@v1.0.3 uses: michaelkaye/setup-matrix-synapse@v1.0.4
with: with:
uploadLogs: true uploadLogs: true
httpPort: 8080 httpPort: 8080
@ -94,7 +95,7 @@ jobs:
needs: needs:
- should-i-run - should-i-run
- ui-tests - ui-tests
if: always() && (needs.should-i-run.result == 'success' ) && ((needs.codecov-units.result != 'success' ) || (needs.ui-tests.result != 'success') || (needs.integration-tests.result != 'success')) if: always() && (needs.should-i-run.result == 'success' ) && (needs.ui-tests.result != 'success')
# No concurrency required, runs every time on a schedule. # No concurrency required, runs every time on a schedule.
steps: steps:
- uses: michaelkaye/matrix-hookshot-action@v1.0.0 - uses: michaelkaye/matrix-hookshot-action@v1.0.0

View file

@ -7,7 +7,7 @@ on:
# Enrich gradle.properties for CI/CD # Enrich gradle.properties for CI/CD
env: env:
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxPermSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs: jobs:
@ -27,7 +27,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Run knit - name: Run knit
run: | run: |
./gradlew knitCheck ./gradlew knitCheck $CI_GRADLE_ARG_PROPERTIES
# Check the project: ktlint, detekt, lint # Check the project: ktlint, detekt, lint
lint: lint:
@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Run ktlint - name: Run ktlint
run: | run: |
./gradlew ktlintCheck --continue ./gradlew ktlintCheck $CI_GRADLE_ARG_PROPERTIES --continue
- name: Run detekt - name: Run detekt
if: always() if: always()
run: | run: |
@ -49,8 +49,8 @@ jobs:
- name: Run lint - name: Run lint
# Not always, if ktlint or detekt fail, avoid running the long lint check. # Not always, if ktlint or detekt fail, avoid running the long lint check.
run: | run: |
./gradlew lintGplayRelease $CI_GRADLE_ARG_PROPERTIES ./gradlew vector-app:lintGplayRelease $CI_GRADLE_ARG_PROPERTIES
./gradlew lintFdroidRelease $CI_GRADLE_ARG_PROPERTIES ./gradlew vector-app:lintFdroidRelease $CI_GRADLE_ARG_PROPERTIES
- name: Upload reports - name: Upload reports
if: always() if: always()
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@ -66,11 +66,13 @@ jobs:
yarn add danger-plugin-lint-report --dev yarn add danger-plugin-lint-report --dev
- name: Danger lint - name: Danger lint
if: always() if: always()
uses: danger/danger-js@11.1.1 uses: danger/danger-js@11.2.0
with: with:
args: "--dangerfile tools/danger/dangerfile-lint.js" args: "--dangerfile ./tools/danger/dangerfile-lint.js"
env: env:
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
# Fallback for forks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin # Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
dependency-analysis: dependency-analysis:

View file

@ -1,19 +1,23 @@
name: Test name: Test
on: on:
pull_request: {} pull_request: { }
push: push:
branches: [main, develop] branches: [ main, develop ]
# Enrich gradle.properties for CI/CD # Enrich gradle.properties for CI/CD
env: env:
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
jobs: jobs:
tests: tests:
name: Runs all tests name: Runs all tests
runs-on: macos-latest # for the emulator runs-on: buildjet-4vcpu-ubuntu-2204
timeout-minutes: 90 # We might need to increase it if the time for tests grows
strategy:
matrix:
api-level: [28]
# Allow all jobs on main and develop. Just one per PR. # Allow all jobs on main and develop. Just one per PR.
concurrency: concurrency:
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
@ -21,59 +25,91 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
lfs: true
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v3 - uses: actions/setup-java@v3
with: with:
distribution: 'adopt' distribution: 'adopt'
java-version: '11' java-version: '11'
- uses: gradle/gradle-build-action@v2 - uses: gradle/gradle-build-action@v2
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
gradle-home-cache-cleanup: ${{ github.ref == 'refs/heads/develop' }}
- name: Run screenshot tests
run: ./gradlew verifyScreenshots $CI_GRADLE_ARG_PROPERTIES
- name: Archive Screenshot Results on Error
if: failure()
uses: actions/upload-artifact@v3
with:
name: screenshot-results
path: |
**/out/failures/
**/build/reports/tests/*UnitTest/
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: 3.8
- uses: michaelkaye/setup-matrix-synapse@v1.0.3 - uses: michaelkaye/setup-matrix-synapse@v1.0.4
with: with:
uploadLogs: true uploadLogs: true
httpPort: 8080 httpPort: 8080
disableRateLimiting: true disableRateLimiting: true
public_baseurl: "http://10.0.2.2:8080/" public_baseurl: "http://10.0.2.2:8080/"
- name: Run all the codecoverage tests at once - name: Run all the codecoverage tests at once
id: tests
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
continue-on-error: true # continue-on-error: true
with: with:
api-level: 28 api-level: ${{ matrix.api-level }}
arch: x86 arch: x86
profile: Nexus 5X profile: Nexus 5X
target: playstore
force-avd-creation: false force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true disable-animations: true
emulator-build: 7425822 # emulator-build: 7425822
script: |
./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
- name: Run all the codecoverage tests at once (retry if emulator failed)
uses: reactivecircus/android-emulator-runner@v2
if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
with:
api-level: 28
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
disable-animations: true
emulator-build: 7425822
script: | script: |
./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
- run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES # NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves steps.tests.outcome = 'failure'
if: always() # we may have failed a previous step and retried, that's OK ### - name: Run all the codecoverage tests at once (retry if emulator failed)
### uses: reactivecircus/android-emulator-runner@v2
### if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
### with:
### api-level: 28
### 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
### disable-animations: true
### emulator-build: 7425822
### script: |
### ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
### ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
### ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
### ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
- name: Upload Integration Test Report Log
uses: actions/upload-artifact@v3
if: always()
with:
name: integration-test-error-results
path: |
*/build/outputs/androidTest-results/connected/
*/build/reports/androidTests/connected/
# we may have failed a previous step and retried, that's OK
- name: Publish results to Sonar
env: env:
GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
if: ${{ always() && env.GITHUB_TOKEN != '' && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }}
run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
- name: Format unit test results - name: Format unit test results
if: always() if: always()
@ -91,26 +127,26 @@ jobs:
# Unneeded as part of the test suite above, kept around in case we want to re-enable them. # Unneeded as part of the test suite above, kept around in case we want to re-enable them.
# #
# # Build Android Tests # # Build Android Tests
# build-android-tests: # build-android-tests:
# name: Build Android Tests # name: Build Android Tests
# runs-on: ubuntu-latest # runs-on: ubuntu-latest
# concurrency: # concurrency:
# group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }} # group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
# cancel-in-progress: true # cancel-in-progress: true
# steps: # steps:
# - uses: actions/checkout@v3 # - uses: actions/checkout@v3
# - uses: actions/setup-java@v3 # - uses: actions/setup-java@v3
# with: # with:
# distribution: 'adopt' # distribution: 'adopt'
# java-version: 11 # java-version: 11
# - uses: actions/cache@v3 # - uses: actions/cache@v3
# with: # with:
# path: | # path: |
# ~/.gradle/caches # ~/.gradle/caches
# ~/.gradle/wrapper # ~/.gradle/wrapper
# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} # key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
# restore-keys: | # restore-keys: |
# ${{ runner.os }}-gradle- # ${{ runner.os }}-gradle-
# - name: Build Android Tests # - name: Build Android Tests
# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES # run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES

View file

@ -10,7 +10,7 @@ jobs:
# Skip in forks # Skip in forks
if: github.repository == 'vector-im/element-android' if: github.repository == 'vector-im/element-android'
steps: steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 - uses: alex-page/github-project-automation-plus@1f8873e97e3c8f58161a323b7c568c1f623a1c4d
with: with:
project: Issue triage project: Issue triage
column: Incoming column: Incoming

View file

@ -17,7 +17,8 @@ jobs:
contains(github.event.issue.labels.*.name, 'Z-IA') || contains(github.event.issue.labels.*.name, 'Z-IA') ||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') || contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') || contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
contains(github.event.issue.labels.*.name, 'A-Tags') contains(github.event.issue.labels.*.name, 'A-Tags') ||
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
steps: steps:
- uses: actions/github-script@v5 - uses: actions/github-script@v5
with: with:
@ -29,6 +30,23 @@ jobs:
labels: ['Z-Labs'] labels: ['Z-Labs']
}) })
apply_Help-Wanted_label:
name: Add "Help Wanted" label to all "good first issue" and Hacktoberfest
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'good first issue') ||
contains(github.event.issue.labels.*.name, 'Hacktoberfest')
steps:
- uses: actions/github-script@v5
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Help Wanted']
})
move_needs_info_issues: move_needs_info_issues:
name: X-Needs-Info issues to Need info column on triage board name: X-Needs-Info issues to Need info column on triage board
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -48,7 +66,13 @@ jobs:
# Skip in forks # Skip in forks
if: > if: >
github.repository == 'vector-im/element-android' && github.repository == 'vector-im/element-android' &&
contains(github.event.issue.labels.*.name, 'X-Needs-Design') contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
(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'))
steps: steps:
- uses: octokit/graphql-action@v2.x - uses: octokit/graphql-action@v2.x
id: add_to_project id: add_to_project
@ -56,8 +80,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -65,7 +89,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc0sUA" PROJECT_ID: "PVT_kwDOAM0swc0sUA"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
add_product_issues: add_product_issues:
@ -80,8 +104,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -89,7 +113,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4AAg6N" PROJECT_ID: "PVT_kwDOAM0swc4AAg6N"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
delight_issues_to_board: delight_issues_to_board:
@ -98,15 +122,16 @@ jobs:
# Skip in forks # Skip in forks
if: > if: >
github.repository == 'vector-im/element-android' && github.repository == 'vector-im/element-android' &&
(contains(github.event.issue.labels.*.name, 'Team: Delight')) (contains(github.event.issue.labels.*.name, 'Team: Delight') ||
contains(github.event.issue.labels.*.name, 'Z-AppLayout'))
steps: steps:
- uses: octokit/graphql-action@v2.x - uses: octokit/graphql-action@v2.x
with: with:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -114,7 +139,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc1HvQ" PROJECT_ID: "PVT_kwDOAM0swc1HvQ"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_voice-message_issues: move_voice-message_issues:
@ -130,8 +155,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -139,34 +164,8 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc2KCw" PROJECT_ID: "PVT_kwDOAM0swc2KCw"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_threads_issues:
name: A-Threads to Thread board
runs-on: ubuntu-latest
# Skip in forks
if: >
github.repository == 'vector-im/element-android' &&
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:ID!,$contentid:ID!) {
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 }}
move_message_bubbles_issues: move_message_bubbles_issues:
name: A-Message-Bubbles to Message bubbles board name: A-Message-Bubbles to Message bubbles board
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -180,8 +179,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -189,7 +188,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc3m-g" PROJECT_ID: "PVT_kwDOAM0swc3m-g"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_ftue_issues: move_ftue_issues:
@ -205,8 +204,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -214,7 +213,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4AAqVx" PROJECT_ID: "PVT_kwDOAM0swc4AAqVx"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_WTF_issues: move_WTF_issues:
@ -230,8 +229,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -239,7 +238,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4AArk0" PROJECT_ID: "PVT_kwDOAM0swc4AArk0"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_element_x_issues: move_element_x_issues:
@ -260,8 +259,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) { mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -269,5 +268,107 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4ABTXY" PROJECT_ID: "PVT_kwDOAM0swc4ABTXY"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features1:
name: Add labelled issues to PS features team 1
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Polls') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
(contains(github.event.issue.labels.*.name, 'A-Voice-Messages') &&
!contains(github.event.issue.labels.*.name, 'A-Broadcast')) ||
(contains(github.event.issue.labels.*.name, 'A-Session-Mgmt') &&
contains(github.event.issue.labels.*.name, 'A-User-Settings'))
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKF"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features2:
name: Add labelled issues to PS features team 2
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-DM-Start') ||
contains(github.event.issue.labels.*.name, 'A-Broadcast')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKd"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features3:
name: Add labelled issues to PS features team 3
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKW"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
voip:
name: Add labelled issues to VoIP project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Team: VoIP')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4ABMIk"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -60,8 +60,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!, $contentid:ID!) { mutation add_to_project($projectid:ID!, $contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -69,7 +69,7 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.pull_request.node_id }} contentid: ${{ github.event.pull_request.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc0sUA" PROJECT_ID: "PVT_kwDOAM0swc0sUA"
TEAM: "design" TEAM: "design"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
@ -129,8 +129,8 @@ jobs:
headers: '{"GraphQL-Features": "projects_next_graphql"}' headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: | query: |
mutation add_to_project($projectid:ID!, $contentid:ID!) { mutation add_to_project($projectid:ID!, $contentid:ID!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
projectNextItem { item {
id id
} }
} }
@ -138,6 +138,6 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.pull_request.node_id }} contentid: ${{ github.event.pull_request.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4AAg6N" PROJECT_ID: "PVT_kwDOAM0swc4AAg6N"
TEAM: "product" TEAM: "product"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -24,10 +24,10 @@ jobs:
contains(github.event.issue.labels.*.name, 'A11y') && contains(github.event.issue.labels.*.name, 'A11y') &&
contains(github.event.issue.labels.*.name, 'O-Frequent')) contains(github.event.issue.labels.*.name, 'O-Frequent'))
steps: steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 - uses: alex-page/github-project-automation-plus@1f8873e97e3c8f58161a323b7c568c1f623a1c4d
with: with:
project: Android App Team project: Android App Team
column: P1 column: Important Issues & Topics (P1)
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
P1_issues_to_crypto_team_workboard: P1_issues_to_crypto_team_workboard:
@ -50,7 +50,7 @@ jobs:
contains(github.event.issue.labels.*.name, 'A11y') && contains(github.event.issue.labels.*.name, 'A11y') &&
contains(github.event.issue.labels.*.name, 'O-Frequent'))) contains(github.event.issue.labels.*.name, 'O-Frequent')))
steps: steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 - uses: alex-page/github-project-automation-plus@1f8873e97e3c8f58161a323b7c568c1f623a1c4d
with: with:
project: Crypto Team project: Crypto Team
column: Ready column: Ready

View file

@ -28,7 +28,7 @@ jobs:
echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV
fi fi
- name: Move issue - name: Move issue
uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 uses: alex-page/github-project-automation-plus@1f8873e97e3c8f58161a323b7c568c1f623a1c4d
if: ${{ env.ALREADY_IN_BOARD == 'true' }} if: ${{ env.ALREADY_IN_BOARD == 'true' }}
with: with:
project: Issue triage project: Issue triage

15
.github/workflows/validate-lfs.yml vendored Normal file
View file

@ -0,0 +1,15 @@
name: Validate Git LFS
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
name: Validate
steps:
- uses: actions/checkout@v3
with:
lfs: 'true'
- run: |
./tools/validate_lfs.sh

1
.gitignore vendored
View file

@ -22,3 +22,4 @@
/package.json /package.json
/yarn.lock /yarn.lock
/node_modules /node_modules
**/out/failures

View file

@ -1,3 +1,511 @@
Changes in Element v1.5.18 (2023-01-02)
=======================================
This release fixes a bunch of recent regressions. Most of them were not pushed to production hopefully. Current production version is 1.5.11.
Threads are now enabled by default, and this may let the application perform an initial sync.
Testers on the PlayStore may have experimented some issues like empty room list, or incomplete room state (room name missing, etc.), or even crashing due to initial sync not using lazy loading of room members. All those issues have been fixed, but to fix your current state, please clear cache once you get the release 1.5.18.
Bugfixes 🐛
----------
- Start DM will create a deadlock if user profile was never loaded ([#7870](https://github.com/vector-im/element-android/issues/7870))
Changes in Element v1.5.16 (2022-12-29)
======================================
Features ✨
----------
- [Rich text editor] Add support for links ([#7746](https://github.com/vector-im/element-android/issues/7746))
- [Poll] When a poll is ended, use /relations API to ensure poll results are correct ([#7767](https://github.com/vector-im/element-android/issues/7767))
- [Session manager] Security recommendations cards: whole view should be tappable ([#7795](https://github.com/vector-im/element-android/issues/7795))
- [Session manager] Other sessions list: header should not be sticky ([#7797](https://github.com/vector-im/element-android/issues/7797))
Bugfixes 🐛
----------
- Do not show typing notification of ignored users. ([#2965](https://github.com/vector-im/element-android/issues/2965))
- [Push Notifications, Threads] - quick reply to threaded notification now sent to thread except main timeline ([#7475](https://github.com/vector-im/element-android/issues/7475))
- [Session manager] Other sessions list: filter option is displayed when selection mode is enabled ([#7784](https://github.com/vector-im/element-android/issues/7784))
- [Session manager] Other sessions: Filter bottom sheet cut in landscape mode ([#7786](https://github.com/vector-im/element-android/issues/7786))
- Automatically show keyboard after learn more bottom sheet is dismissed ([#7790](https://github.com/vector-im/element-android/issues/7790))
- [Session Manager] Other sessions list: cannot select/deselect session by a long press when in select mode ([#7792](https://github.com/vector-im/element-android/issues/7792))
- Fix current session ip address visibility ([#7794](https://github.com/vector-im/element-android/issues/7794))
- Device Manager UI review fixes ([#7798](https://github.com/vector-im/element-android/issues/7798))
SDK API changes ⚠️
------------------
- [Sync] Sync Filter params are moved to MatrixConfiguration and will not be stored in session realm to avoid bug when session cache is cleared ([#7843](https://github.com/vector-im/element-android/issues/7843))
Other changes
-------------
- [Voice Broadcast] Replace the player timeline ([#7821](https://github.com/vector-im/element-android/issues/7821))
- Increase session manager test coverage ([#7836](https://github.com/vector-im/element-android/issues/7836))
Changes in Element v1.5.14 (2022-12-20)
=======================================
Bugfixes 🐛
----------
- ActiveSessionHolder is not supposed to start syncing. Instead, the MainActivity does it, if necessary. Fixes a race condition when clearing cache.
Changes in Element v1.5.13 (2022-12-19)
=======================================
Bugfixes 🐛
----------
- Add `largeHeap=true` in the manifest since we are seeing more crashes (OOM) when handling sync response.
Changes in Element v1.5.12 (2022-12-15)
=======================================
Features ✨
----------
- [Threads] - Threads Labs Flag is enabled by default and forced to be enabled for existing users, but sill can be disabled manually ([#5503](https://github.com/vector-im/element-android/issues/5503))
- [Session manager] Add action to signout all the other session ([#7693](https://github.com/vector-im/element-android/issues/7693))
- Remind unverified sessions with a banner once a week ([#7694](https://github.com/vector-im/element-android/issues/7694))
- [Session manager] Add actions to rename and signout current session ([#7697](https://github.com/vector-im/element-android/issues/7697))
- Voice Broadcast - Update last message in the room list ([#7719](https://github.com/vector-im/element-android/issues/7719))
- Delete unused client information from account data ([#7754](https://github.com/vector-im/element-android/issues/7754))
Bugfixes 🐛
----------
- Fix bad pills color background. For light and dark theme the color is now 61708B (iso EleWeb) ([#7274](https://github.com/vector-im/element-android/issues/7274))
- [Notifications] Fixed a bug when push notification was automatically dismissed while app is on background ([#7643](https://github.com/vector-im/element-android/issues/7643))
- ANR when asking to select the notification method ([#7653](https://github.com/vector-im/element-android/issues/7653))
- [Rich text editor] Fix design and spacing of rich text editor ([#7658](https://github.com/vector-im/element-android/issues/7658))
- [Rich text editor] Fix keyboard closing after collapsing editor ([#7659](https://github.com/vector-im/element-android/issues/7659))
- Rich Text Editor: fix several issues related to insets:
* Empty space displayed at the bottom when you don't have permissions to send messages into a room.
* Wrong insets being kept when you exit the room screen and the keyboard is displayed, then come back to it. ([#7680](https://github.com/vector-im/element-android/issues/7680))
- Fix crash in message composer when room is missing ([#7683](https://github.com/vector-im/element-android/issues/7683))
- Fix crash when invalid homeserver url is entered. ([#7684](https://github.com/vector-im/element-android/issues/7684))
- Rich Text Editor: improve performance when entering reply/edit/quote mode. ([#7691](https://github.com/vector-im/element-android/issues/7691))
- [Rich text editor] Add error tracking for rich text editor ([#7695](https://github.com/vector-im/element-android/issues/7695))
- Fix E2EE set up failure whilst signing in using QR code ([#7699](https://github.com/vector-im/element-android/issues/7699))
- Fix usage of unknown shield in room summary ([#7710](https://github.com/vector-im/element-android/issues/7710))
- Fix crash when the network is not available. ([#7725](https://github.com/vector-im/element-android/issues/7725))
- [Session manager] Sessions without encryption support should not prompt to verify ([#7733](https://github.com/vector-im/element-android/issues/7733))
- Fix issue of Scan QR code button sometimes not showing when it should be available ([#7737](https://github.com/vector-im/element-android/issues/7737))
- Verification request is not showing when verify session popup is displayed ([#7743](https://github.com/vector-im/element-android/issues/7743))
- Fix crash when inviting by email. ([#7744](https://github.com/vector-im/element-android/issues/7744))
- Revert usage of stable fields in live location sharing and polls ([#7751](https://github.com/vector-im/element-android/issues/7751))
- [Poll] Poll end event is not recognized ([#7753](https://github.com/vector-im/element-android/issues/7753))
- [Push Notifications] When push notification for threaded message is clicked, thread timeline will be opened instead of room's main timeline ([#7770](https://github.com/vector-im/element-android/issues/7770))
Other changes
-------------
- [Threads] - added API to fetch threads list from the server instead of building it locally from events ([#5819](https://github.com/vector-im/element-android/issues/5819))
- Add Z-Labs label for rich text editor and migrate to new label naming. ([#7477](https://github.com/vector-im/element-android/issues/7477))
- Crypto database migration tests ([#7645](https://github.com/vector-im/element-android/issues/7645))
- Add tracing Id for to device messages ([#7708](https://github.com/vector-im/element-android/issues/7708))
- Disable nightly popup and add an entry point in the advanced settings instead. ([#7723](https://github.com/vector-im/element-android/issues/7723))
- Save m.local_notification_settings.<device-id> event in account_data ([#7596](https://github.com/vector-im/element-android/issues/7596))
- Update notifications setting when m.local_notification_settings.<device-id> event changes for current device ([#7632](https://github.com/vector-im/element-android/issues/7632))
SDK API changes ⚠️
------------------
- Handle account data removal ([#7740](https://github.com/vector-im/element-android/issues/7740))
Changes in Element 1.5.11 (2022-12-07)
======================================
Bugfixes 🐛
----------
- Fix crash when the network is not available. ([#7725](https://github.com/vector-im/element-android/issues/7725))
Changes in Element v1.5.10 (2022-11-30)
=======================================
Features ✨
----------
- Add setting to allow disabling direct share ([#2725](https://github.com/vector-im/element-android/issues/2725))
- [Device Manager] Toggle IP address visibility ([#7546](https://github.com/vector-im/element-android/issues/7546))
- New implementation of the full screen mode for the Rich Text Editor. ([#7577](https://github.com/vector-im/element-android/issues/7577))
Bugfixes 🐛
----------
- Fix italic text is truncated when bubble mode and markdown is enabled ([#5679](https://github.com/vector-im/element-android/issues/5679))
- Missing translations on "replyTo" messages ([#7555](https://github.com/vector-im/element-android/issues/7555))
- ANR on session start when sending client info is enabled ([#7604](https://github.com/vector-im/element-android/issues/7604))
- Make the plain text mode layout of the RTE more compact. ([#7620](https://github.com/vector-im/element-android/issues/7620))
- Push notification for thread message is now shown correctly when user observes rooms main timeline ([#7634](https://github.com/vector-im/element-android/issues/7634))
- Voice Broadcast - Fix playback stuck in buffering mode ([#7646](https://github.com/vector-im/element-android/issues/7646))
In development 🚧
----------------
- Voice Broadcast - Handle redaction of the state events on the listener and recorder sides ([#7629](https://github.com/vector-im/element-android/issues/7629))
- Voice Broadcast - Update the buffering display in the timeline ([#7655](https://github.com/vector-im/element-android/issues/7655))
- Voice Broadcast - Remove voice messages related to a VB from the room attachments ([#7656](https://github.com/vector-im/element-android/issues/7656))
SDK API changes ⚠️
------------------
- Added support for read receipts in threads. Now user in a room can have multiple read receipts (one per thread + one in main thread + one without threadId) ([#6996](https://github.com/vector-im/element-android/issues/6996))
- Sync Filter now taking in account homeserver capabilities to not pass unsupported parameters.
Sync Filter is now configured by providing SyncFilterBuilder class instance, instead of Filter to identify Filter changes related to homeserver capabilities ([#7626](https://github.com/vector-im/element-android/issues/7626))
Other changes
-------------
- Remove usage of Buildkite. ([#7583](https://github.com/vector-im/element-android/issues/7583))
- Better validation of edits ([#7594](https://github.com/vector-im/element-android/issues/7594))
Changes in Element v1.5.8 (2022-11-17)
======================================
Features ✨
----------
- [Session manager] Multi-session signout ([#7418](https://github.com/vector-im/element-android/issues/7418))
- Rich text editor: add full screen mode. ([#7436](https://github.com/vector-im/element-android/issues/7436))
- [Rich text editor] Add plain text mode ([#7452](https://github.com/vector-im/element-android/issues/7452))
- Move TypingView inside the timeline items. ([#7496](https://github.com/vector-im/element-android/issues/7496))
- Push notifications toggle: align implementation for current session ([#7512](https://github.com/vector-im/element-android/issues/7512))
- Voice messages - Persist the playback position across different screens ([#7582](https://github.com/vector-im/element-android/issues/7582))
Bugfixes 🐛
----------
- [Voice Broadcast] Do not display the recorder view for a live broadcast started from another session ([#7431](https://github.com/vector-im/element-android/issues/7431))
- [Session manager] Hide push notification toggle when there is no server support ([#7457](https://github.com/vector-im/element-android/issues/7457))
- Fix rich text editor textfield not growing to fill parent on full screen. ([#7491](https://github.com/vector-im/element-android/issues/7491))
- Fix duplicated mention pills in some cases ([#7501](https://github.com/vector-im/element-android/issues/7501))
- Voice Broadcast - Fix duplicated voice messages in the internal playlist ([#7502](https://github.com/vector-im/element-android/issues/7502))
- When joining a room, the message composer is displayed once the room is loaded. ([#7509](https://github.com/vector-im/element-android/issues/7509))
- Voice Broadcast - Fix error on voice messages in unencrypted rooms ([#7519](https://github.com/vector-im/element-android/issues/7519))
- Fix description of verified sessions ([#7533](https://github.com/vector-im/element-android/issues/7533))
In development 🚧
----------------
- [Voice Broadcast] Improve timeline items factory and handle bad recording state display ([#7448](https://github.com/vector-im/element-android/issues/7448))
- [Voice Broadcast] Stop recording when opening the room after an app restart ([#7450](https://github.com/vector-im/element-android/issues/7450))
- [Voice Broadcast] Improve playlist fetching and player codebase ([#7478](https://github.com/vector-im/element-android/issues/7478))
- [Voice Broadcast] Display an error dialog if the user fails to start a voice broadcast ([#7485](https://github.com/vector-im/element-android/issues/7485))
- [Voice Broadcast] Add seekbar in listening tile ([#7496](https://github.com/vector-im/element-android/issues/7496))
- [Voice Broadcast] Improve the live indicator icon rendering in the timeline ([#7579](https://github.com/vector-im/element-android/issues/7579))
- Voice Broadcast - Add maximum length ([#7588](https://github.com/vector-im/element-android/issues/7588))
SDK API changes ⚠️
------------------
- [Metrics] Add `SpannableMetricPlugin` to support spans within transactions. ([#7514](https://github.com/vector-im/element-android/issues/7514))
- Fix a bug that caused messages with no formatted text to be quoted as "null". ([#7530](https://github.com/vector-im/element-android/issues/7530))
- If message content has no `formattedBody`, default to `body` when editing. ([#7574](https://github.com/vector-im/element-android/issues/7574))
Changes in Element v1.5.7 (2022-11-07)
======================================
Bugfixes 🐛
----------
- Fix regression when syncing with homeserver < 1.4. ([#7534](https://github.com/vector-im/element-android/issues/7534))
Changes in Element v1.5.6 (2022-11-02)
======================================
Features ✨
----------
- Add new UI for selecting an attachment ([#7429](https://github.com/vector-im/element-android/issues/7429))
- Multi selection in sessions list ([#7396](https://github.com/vector-im/element-android/issues/7396))
Bugfixes 🐛
----------
- New line and Enter hardware key presses deleting existing text in some keyboards. ([#7357](https://github.com/vector-im/element-android/issues/7357))
- Fix share actions using share dialog. ([#7400](https://github.com/vector-im/element-android/issues/7400))
- Fix crash by disabling Flipper on Android API 22 and below - only affects debug version of the application. ([#7428](https://github.com/vector-im/element-android/issues/7428))
In development 🚧
----------------
- [Voice Broadcast] Live listening support ([#7419](https://github.com/vector-im/element-android/issues/7419))
- [Voice Broadcast] Improve rendering in the timeline ([#7421](https://github.com/vector-im/element-android/issues/7421))
- Add logic for sign in with QR code ([#7369](https://github.com/vector-im/element-android/issues/7369))
SDK API changes ⚠️
------------------
- Add MetricPlugin interface to implement metrics in SDK clients. ([#7438](https://github.com/vector-im/element-android/issues/7438))
Other changes
-------------
- Upgrade Jitsi SDK to 6.2.2 and WebRtc to 1.106.1-jitsi-12039821. ([#6195](https://github.com/vector-im/element-android/issues/6195))
- Gets thread notifications from sync response ([#7424](https://github.com/vector-im/element-android/issues/7424))
- Replace org.apache.sanselan:sanselan by org.apache.commons:commons-imaging ([#7454](https://github.com/vector-im/element-android/issues/7454))
Changes in Element v1.5.4 (2022-10-19)
======================================
Features ✨
----------
- Add WYSIWYG editor, under a lab flag. ([#7288](https://github.com/vector-im/element-android/issues/7288))
- New Device management, can be enabled in the labs settings.
- Voice broadcast can be enabled in the labs settings (recording is possible only on Android 10 and up).
Bugfixes 🐛
----------
- Fix wrong mic button direction to cancel on RTL languages ([#5968](https://github.com/vector-im/element-android/issues/5968))
- Handle properly when getUser returns null - prefer using getUserOrDefault ([#7372](https://github.com/vector-im/element-android/issues/7372))
- [Device Management] Long session names not handled well ([#7310](https://github.com/vector-im/element-android/issues/7310))
- Fix editing formatted messages with plain text editor ([#7359](https://github.com/vector-im/element-android/issues/7359))
In development 🚧
----------------
- [Device Management] Save "matrix_client_information" events on login/registration ([#7257](https://github.com/vector-im/element-android/issues/7257))
- [Device management] Add lab flag for the feature ([#7336](https://github.com/vector-im/element-android/issues/7336))
- [Device management] Add lab flag for matrix client info account data event ([#7344](https://github.com/vector-im/element-android/issues/7344))
- [Device Management] Redirect to the new screen everywhere when lab flag is on ([#7374](https://github.com/vector-im/element-android/issues/7374))
- [Device Management] Show correct device type icons ([#7277](https://github.com/vector-im/element-android/issues/7277))
- [Device Management] Render extended device info ([#7294](https://github.com/vector-im/element-android/issues/7294))
- [Device management] Improve the parsing for OS of Desktop/Web sessions ([#7321](https://github.com/vector-im/element-android/issues/7321))
- [Device management] Hide the IP address and last activity date on current session ([#7324](https://github.com/vector-im/element-android/issues/7324))
- [Device management] Update the unknown verification status icon ([#7327](https://github.com/vector-im/element-android/issues/7327))
- [Voice Broadcast] Add the "io.element.voice_broadcast_info" state event with a minimalist timeline widget ([#7273](https://github.com/vector-im/element-android/issues/7273))
- [Voice Broadcast] Aggregate state events in the timeline ([#7283](https://github.com/vector-im/element-android/issues/7283))
- [Voice Broadcast] Record and send non aggregated voice messages to the room ([#7363](https://github.com/vector-im/element-android/issues/7363))
- [Voice Broadcast] Start listening to a voice broadcast ([#7387](https://github.com/vector-im/element-android/issues/7387))
- [Voice Broadcast] Enable the feature (behind a lab flag and only for Android 10 and up) ([#7393](https://github.com/vector-im/element-android/issues/7393))
- [Voice Broadcast] Add additional data in events ([#7397](https://github.com/vector-im/element-android/issues/7397))
- Implements MSC3881: Parses `enabled` and `device_id` fields from updated Pusher API ([#7217](https://github.com/vector-im/element-android/issues/7217))
- Adds pusher toggle setting to device manager v2 ([#7261](https://github.com/vector-im/element-android/issues/7261))
- Implement QR Code Login UI ([#7338](https://github.com/vector-im/element-android/issues/7338))
- Implements client-side of local notification settings event ([#7300](https://github.com/vector-im/element-android/issues/7300))
- Links "Enable Notifications for this session" setting to enabled value in pusher ([#7281](https://github.com/vector-im/element-android/issues/7281))
SDK API changes ⚠️
------------------
- Stop using `original_event` field from `/relations` endpoint ([#7282](https://github.com/vector-im/element-android/issues/7282))
- Add `formattedText` or similar optional parameters in several methods:
* RelationService:
* editTextMessage
* editReply
* replyToMessage
* SendService:
* sendQuotedTextMessage
This allows us to send any HTML formatted text message without needing to rely on automatic Markdown > HTML translation. All these new parameters have a `null` value by default, so previous calls to these API methods remain compatible. ([#7288](https://github.com/vector-im/element-android/issues/7288))
- Add support for `m.login.token` auth during QR code based sign in ([#7358](https://github.com/vector-im/element-android/issues/7358))
- Allow getting the formatted or plain text body of a message for the fun `TimelineEvent.getTextEditableContent()`. ([#7359](https://github.com/vector-im/element-android/issues/7359))
Other changes
-------------
- Refactor TimelineFragment, split it into MessageComposerFragment and VoiceRecorderFragment. ([#7285](https://github.com/vector-im/element-android/issues/7285))
- Dependency to arrow has been removed. Please use `org.matrix.android.sdk.api.util.Optional` instead. ([#7335](https://github.com/vector-im/element-android/issues/7335))
- Update WYSIWYG editor designs. ([#7354](https://github.com/vector-im/element-android/issues/7354))
- Update WYSIWYG library to v0.2.1. ([#7384](https://github.com/vector-im/element-android/issues/7384))
Changes in Element v1.5.2 (2022-10-05)
======================================
Features ✨
----------
- New App Layout is now enabled by default! Go to the Settings > Labs to toggle this ([#7166](https://github.com/vector-im/element-android/issues/7166))
- Render inline images in the timeline ([#351](https://github.com/vector-im/element-android/issues/351))
- Add privacy setting to disable personalized learning by the keyboard ([#6633](https://github.com/vector-im/element-android/issues/6633))
Bugfixes 🐛
----------
- Disable emoji keyboard not applies in reply ([#5029](https://github.com/vector-im/element-android/issues/5029))
- Fix animated images not autoplaying sometimes if only a thumbnail was fetched from the server ([#6215](https://github.com/vector-im/element-android/issues/6215))
- Add Warning shield when a user previously verified rotated their cross signing keys ([#6702](https://github.com/vector-im/element-android/issues/6702))
- Can't verify user when option to send keys to verified devices only is selected ([#6723](https://github.com/vector-im/element-android/issues/6723))
- Add option to only send to verified devices per room (web parity) ([#6725](https://github.com/vector-im/element-android/issues/6725))
- Delete pin code key and the key used for biometrics authentication on logout ([#6906](https://github.com/vector-im/element-android/issues/6906))
- Fix crash on previewing images to upload on Android Pie. ([#7184](https://github.com/vector-im/element-android/issues/7184))
- Fix app restarts in loop on Android 13 on the first run of the app. ([#7224](https://github.com/vector-im/element-android/issues/7224))
In development 🚧
----------------
- [Device Management] Learn more bottom sheets ([#7100](https://github.com/vector-im/element-android/issues/7100))
- [Device management] Verify current session ([#7114](https://github.com/vector-im/element-android/issues/7114))
- [Device management] Verify another session ([#7143](https://github.com/vector-im/element-android/issues/7143))
- [Device management] Rename a session ([#7158](https://github.com/vector-im/element-android/issues/7158))
- [Device Manager] Unverified and inactive sessions list ([#7170](https://github.com/vector-im/element-android/issues/7170))
- [Device management] Sign out a session ([#7190](https://github.com/vector-im/element-android/issues/7190))
- [Device Manager] Parse user agents ([#7247](https://github.com/vector-im/element-android/issues/7247))
- [Voice Broadcast] Add a feature flag with the composer action ([#7258](https://github.com/vector-im/element-android/issues/7258))
Improved Documentation 📚
------------------------
- Draft onboarding documentation of the project at `./docs/_developer_onboarding.md` ([#7126](https://github.com/vector-im/element-android/issues/7126))
SDK API changes ⚠️
------------------
- Allow the sync timeout to be configured (mainly useful for testing) ([#7198](https://github.com/vector-im/element-android/issues/7198))
- Ports SDK instrumentation tests to use suspending functions instead of countdown latches ([#7207](https://github.com/vector-im/element-android/issues/7207))
- [Device Manager] Extend user agent to include device information ([#7209](https://github.com/vector-im/element-android/issues/7209))
Other changes
-------------
- Add support for `/tableflip` command ([#12](https://github.com/vector-im/element-android/issues/12))
- Decreases the size of rounded corners and increases the maximum width of message bubbles to help avoid unnecessary unused space on screen ([#5712](https://github.com/vector-im/element-android/issues/5712))
- Adds screenshot testing tooling ([#5798](https://github.com/vector-im/element-android/issues/5798))
- [AppLayout]: added tracking of new analytics events ([#6508](https://github.com/vector-im/element-android/issues/6508))
- Target API 12 and compile with Android SDK 32. ([#6929](https://github.com/vector-im/element-android/issues/6929))
- Add basic integration of Sentry to capture errors and crashes if user has given consent. ([#7076](https://github.com/vector-im/element-android/issues/7076))
- Add support to `/devtools` command. ([#7126](https://github.com/vector-im/element-android/issues/7126))
- Fix lint warning, and cleanup the code ([#7159](https://github.com/vector-im/element-android/issues/7159))
- Mutualize the pending auth handling ([#7193](https://github.com/vector-im/element-android/issues/7193))
- CI: Prevent modification of translations by developer. ([#7211](https://github.com/vector-im/element-android/issues/7211))
- Fix typo in strings.xml and make sure this is American English. ([#7287](https://github.com/vector-im/element-android/issues/7287))
Changes in Element v1.5.1 (2022-09-28)
======================================
Security ⚠️
----------
This update provides important security fixes, update now.
Ref: CVE-2022-39246 CVE-2022-39248
Changes in Element v1.5.0 (2022-09-23)
======================================
Features ✨
----------
- Deferred DMs - Enable and move the feature to labs settings ([#7180](https://github.com/vector-im/element-android/issues/7180))
Bugfixes 🐛
----------
- Fix text margin in QR code view when no display name is set ([#5424](https://github.com/vector-im/element-android/issues/5424))
- [App Layout] Recents carousel now scrolled to first position when new item added to or moved to this position ([#6776](https://github.com/vector-im/element-android/issues/6776))
- Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items ([#7079](https://github.com/vector-im/element-android/issues/7079))
- Fixes crash when quickly double clicking FABs in the new app layout ([#7102](https://github.com/vector-im/element-android/issues/7102))
- Fixes space list and new chat bottom sheets showing too small in New App Layout (especially evident in landscape) ([#7103](https://github.com/vector-im/element-android/issues/7103))
- [App Layout] Room leaving prompt dialog now waits user to confirm leaving before do so ([#7122](https://github.com/vector-im/element-android/issues/7122))
- Fix empty verification bottom sheet. ([#7130](https://github.com/vector-im/element-android/issues/7130))
- [New Layout] Fixes new chat dialog not getting dismissed after selecting its actions ([#7132](https://github.com/vector-im/element-android/issues/7132))
- Fixes Room List not getting updated when fragment is not in focus ([#7186](https://github.com/vector-im/element-android/issues/7186))
In development 🚧
----------------
- Create DM room only on first message - Add a spinner when sending the first message ([#6970](https://github.com/vector-im/element-android/issues/6970))
- [Device Manager] Filter Other Sessions ([#7045](https://github.com/vector-im/element-android/issues/7045))
- [Device management] Session details screen ([#7077](https://github.com/vector-im/element-android/issues/7077))
- Create DM room only on first message - Fix glitch in the room list ([#7121](https://github.com/vector-im/element-android/issues/7121))
- Create DM room only on first message - Handle the local rooms within the new AppLayout ([#7153](https://github.com/vector-im/element-android/issues/7153))
Other changes
-------------
- [Modules] Lifts the application variants to the app module ([#6779](https://github.com/vector-im/element-android/issues/6779))
- Ensure that we do not expect all the Event fields when requesting `rooms/{roomId}/hierarchy` endpoint. ([#7035](https://github.com/vector-im/element-android/issues/7035))
- Move some GitHub actions to buildjet runners, and remove the second attempt to run integration tests. ([#7108](https://github.com/vector-im/element-android/issues/7108))
- Exclude legacy android support annotation library ([#7140](https://github.com/vector-im/element-android/issues/7140))
- Pulling no longer hosted im.dlg:android-dialer directly into the repository and removing legacy support library usages ([#7142](https://github.com/vector-im/element-android/issues/7142))
- Fixing build cache misses when compiling the vector module ([#7157](https://github.com/vector-im/element-android/issues/7157))
Changes in Element v1.4.36 (2022-09-10)
=======================================
New App Layout can be enabled in the Labs settings. Please give it a try!
Features ✨
----------
- Adds New App Layout into Labs ([#7038](https://github.com/vector-im/element-android/issues/7038))
- Try to detect devices that lack Opus encoder support, use bundled libopus library for those. ([#7010](https://github.com/vector-im/element-android/issues/7010))
- Suggest @room when @channel, @everyone, or @here is typed in composer ([#6529](https://github.com/vector-im/element-android/issues/6529))
Bugfixes 🐛
----------
- Fix long incremental sync. ([#6917](https://github.com/vector-im/element-android/issues/6917))
- Fix push with FCM ([#7068](https://github.com/vector-im/element-android/issues/7068))
- FTUE - Fixes optional email registration step always being mandatory ([#6969](https://github.com/vector-im/element-android/issues/6969))
- Fixes /addToSpace and /joinSpace commands showing invalid syntax warnings ([#6844](https://github.com/vector-im/element-android/issues/6844))
- Fix low occurrence crashes. ([#6967](https://github.com/vector-im/element-android/issues/6967))
- Fix crash when opening an unknown room ([#6978](https://github.com/vector-im/element-android/issues/6978))
- Fix crash on PIN code settings screen. ([#6979](https://github.com/vector-im/element-android/issues/6979))
- Fix autoplayed animated stickers ([#6982](https://github.com/vector-im/element-android/issues/6982))
- Catch race condition crash in voice recording ([#6989](https://github.com/vector-im/element-android/issues/6989))
- Fix invite to room when in a space buttons not working. ([#7054](https://github.com/vector-im/element-android/issues/7054))
In development 🚧
----------------
- Create DM room only on first message - Create the DM and navigate to the new room after sending an event ([#5525](https://github.com/vector-im/element-android/issues/5525))
- [App Layout] New empty states for home screen ([#6835](https://github.com/vector-im/element-android/issues/6835))
- [App Layout] Bottom navigation tabs are removed for new home screen ([#6565](https://github.com/vector-im/element-android/issues/6565))
- [App Layout] fixed space switching dialog measured with wrong height sometimes ([#6750](https://github.com/vector-im/element-android/issues/6750))
- [App Layout] Fabs doesn't go off screen anymore ([#6765](https://github.com/vector-im/element-android/issues/6765))
- [New Layout] Adds back navigation through spaces ([#6877](https://github.com/vector-im/element-android/issues/6877))
- [App Layout] new room invites screen ([#6889](https://github.com/vector-im/element-android/issues/6889))
- [App Layout] - Invites now show empty screen after you reject last invite ([#6876](https://github.com/vector-im/element-android/issues/6876))
- [App Layout] - space switcher now has empty state ([#6754](https://github.com/vector-im/element-android/issues/6754))
- [App Layout] - Improves Developer Mode Debug Button UX and adds it to New App Layout ([#6871](https://github.com/vector-im/element-android/issues/6871))
- [New Layout] Changes space sheet to accordion-style with expandable subspaces ([#6907](https://github.com/vector-im/element-android/issues/6907))
- [New Layout] Adds space invites ([#6924](https://github.com/vector-im/element-android/issues/6924))
- [App Layout] fixed invites count badge bottom margin on a home screen ([#6947](https://github.com/vector-im/element-android/issues/6947))
- [New Layout] Improves talkback accessibility ([#7016](https://github.com/vector-im/element-android/issues/7016))
- [New Layout] Changes space icon in fab and in release notes screen ([#7039](https://github.com/vector-im/element-android/issues/7039))
- [New Layout] Adds header to spaces bottom sheet ([#7040](https://github.com/vector-im/element-android/issues/7040))
- [App Layout] New App Layout is enabled by default (Edit: has to be enabled in Labs) ([#6958](https://github.com/vector-im/element-android/issues/6958))
- [App Layout] Obsolete settings are not shown when App Layout flag is enabled ([#6646](https://github.com/vector-im/element-android/issues/6646))
- [Devices Management] Session overview screen ([#6961](https://github.com/vector-im/element-android/issues/6961))
- [Devices Management] Refactor some code to improve testability ([#7043](https://github.com/vector-im/element-android/issues/7043))
- [Device Manager] Current Session Section ([#6902](https://github.com/vector-im/element-android/issues/6902))
- [Device Manager] Other Sessions Section ([#6945](https://github.com/vector-im/element-android/issues/6945))
- [Device Manager] Render Security Recommendations ([#6964](https://github.com/vector-im/element-android/issues/6964))
Improved Documentation 📚
------------------------
- Clarify that setting up a FCM Rewrite Proxy is not necessary for use of the UnifiedPush FCM distributor. ([#6727](https://github.com/vector-im/element-android/issues/6727))
Other changes
-------------
- Increase sticker size ([#6982](https://github.com/vector-im/element-android/issues/6982))
- Focus input field when editing homeserver address to speed up login and registration. ([#6926](https://github.com/vector-im/element-android/issues/6926))
- Log basic Http information in production. ([#6925](https://github.com/vector-im/element-android/issues/6925))
- Converts the vector module to a library with a parent vector-app application module ([#6407](https://github.com/vector-im/element-android/issues/6407))
- Creates a dedicated strings module ([#3955](https://github.com/vector-im/element-android/issues/3955))
- Remove FragmentModule and the Fragment factory. No need to Inject the constructor on your Fragment, just add @AndroidEntryPoint annotation and @Inject class members. ([#6894](https://github.com/vector-im/element-android/issues/6894))
- Small refactor of UnifiedPushHelper ([#6936](https://github.com/vector-im/element-android/issues/6936))
- CI: only run sonarqube task when token is known ([#7057](https://github.com/vector-im/element-android/issues/7057))
Changes in Element v1.4.34 (2022-08-23)
=======================================
Features ✨
----------
- [Notification] - Handle creation of notification for live location and poll start ([#6746](https://github.com/vector-im/element-android/issues/6746))
Bugfixes 🐛
----------
- Fixes onboarding requiring matrix.org to be accessible on the first step, the server can now be manually changed ([#6718](https://github.com/vector-im/element-android/issues/6718))
- Fixing sign in/up for homeservers that rely on the SSO fallback url ([#6827](https://github.com/vector-im/element-android/issues/6827))
- Fixes uncaught exceptions in the SyncWorker to cause the worker to become stuck in the failure state ([#6836](https://github.com/vector-im/element-android/issues/6836))
- Fixes onboarding captcha crashing when no WebView is available by showing an error with information instead ([#6855](https://github.com/vector-im/element-android/issues/6855))
- Removes ability to continue registration after the app has been destroyed, fixes the next steps crashing due to missing information from the previous steps ([#6860](https://github.com/vector-im/element-android/issues/6860))
- Fixes crash when exiting the login or registration entry screens whilst they're loading ([#6861](https://github.com/vector-im/element-android/issues/6861))
- Fixes server selection being unable to trust certificates ([#6864](https://github.com/vector-im/element-android/issues/6864))
- Ensure SyncThread is started when the app is launched after a Push has been received. ([#6884](https://github.com/vector-im/element-android/issues/6884))
- Fixes missing firebase notifications after logging in when UnifiedPush distributor is installed ([#6891](https://github.com/vector-im/element-android/issues/6891))
In development 🚧
----------------
- Create DM room only on first message - Trigger the flow when the "Direct Message" action is selected from the room member details screen ([#5525](https://github.com/vector-im/element-android/issues/5525))
- added filter tabs for new App layout's Home screen ([#6505](https://github.com/vector-im/element-android/issues/6505))
- [App Layout] added dialog to configure app layout ([#6506](https://github.com/vector-im/element-android/issues/6506))
- Adds space list bottom sheet for new app layout ([#6749](https://github.com/vector-im/element-android/issues/6749))
- [App Layout] Dialpad moved from bottom navigation tab to a separate activity accessed via home screen context menu ([#6787](https://github.com/vector-im/element-android/issues/6787))
- Makes toolbar switch title based on space in New App Layout ([#6795](https://github.com/vector-im/element-android/issues/6795))
- [Devices management] Add a feature flag and empty screen for future new layout ([#6798](https://github.com/vector-im/element-android/issues/6798))
- Adds new chat bottom sheet as the click action of the main FAB in the new app layout ([#6801](https://github.com/vector-im/element-android/issues/6801))
- [Devices management] Other sessions section in new layout ([#6806](https://github.com/vector-im/element-android/issues/6806))
- [New Layout] Adds space settings accessible through clicking the toolbar ([#6859](https://github.com/vector-im/element-android/issues/6859))
- Adds New App Layout FABs (hidden behind feature flag) ([#6693](https://github.com/vector-im/element-android/issues/6693))
SDK API changes ⚠️
------------------
- Rename `DebugService.logDbUsageInfo` (resp. `Session.logDbUsageInfo`) to `DebugService.getDbUsageInfo` (resp. `Session.getDbUsageInfo`) and return a String instead of logging. The caller may want to log the String. ([#6884](https://github.com/vector-im/element-android/issues/6884))
Other changes
-------------
- Removes the Login2 proof of concept - replaced by the FTUE changes ([#5974](https://github.com/vector-im/element-android/issues/5974))
- Enable auto-capitalization for Room creation Title field ([#6645](https://github.com/vector-im/element-android/issues/6645))
- Decouples the variant logic from the vector module ([#6783](https://github.com/vector-im/element-android/issues/6783))
- Add a developer setting to enable LeakCanary at runtime ([#6786](https://github.com/vector-im/element-android/issues/6786))
- [Create Room] Reduce some boilerplate with room state event contents ([#6799](https://github.com/vector-im/element-android/issues/6799))
- [Call] Memory leak after a call ([#6808](https://github.com/vector-im/element-android/issues/6808))
- Fix some string template ([#6843](https://github.com/vector-im/element-android/issues/6843))
Changes in Element v1.4.32 (2022-08-10) Changes in Element v1.4.32 (2022-08-10)
======================================= =======================================

View file

@ -1,10 +1,43 @@
# Contributing code to Matrix # Contributing to Element Android
<!--- TOC -->
* [Contributing code to Matrix](#contributing-code-to-matrix)
* [Android Studio settings](#android-studio-settings)
* [Template](#template)
* [Compilation](#compilation)
* [I want to help translating Element](#i-want-to-help-translating-element)
* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue)
* [Kotlin](#kotlin)
* [Changelog](#changelog)
* [Code quality](#code-quality)
* [Internal tool](#internal-tool)
* [ktlint](#ktlint)
* [knit](#knit)
* [lint](#lint)
* [Unit tests](#unit-tests)
* [Tests](#tests)
* [Internationalisation](#internationalisation)
* [Adding new string](#adding-new-string)
* [Plurals](#plurals)
* [Editing existing strings](#editing-existing-strings)
* [Removing existing strings](#removing-existing-strings)
* [Renaming string ids](#renaming-string-ids)
* [Reordering strings](#reordering-strings)
* [Accessibility](#accessibility)
* [Layout](#layout)
* [Authors](#authors)
* [Thanks](#thanks)
<!--- END -->
## Contributing code to Matrix
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
Element Android support can be found in this room: [![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org). Element Android support can be found in this room: [![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org).
# Specific rules for Matrix Android projects The rest of the document contains specific rules for Matrix Android projects
## Android Studio settings ## Android Studio settings
@ -94,6 +127,23 @@ Note that you can run
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course) For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
#### knit
[knit](https://github.com/Kotlin/kotlinx-knit) is a tool which checks markdown files on the project. Also it generates/updates the table of content (toc) of the markdown files.
So everytime the toc should be updated, just run
<pre>
./gradlew knit
</pre>
and commit the changes.
The CI will check that markdown files are up to date by running
<pre>
./gradlew knitCheck
</pre>
#### lint #### lint
<pre> <pre>
@ -120,17 +170,21 @@ You should consider adding Unit tests with your PR, and also integration tests (
Translations are handled using an external tool: [Weblate](https://translate.element.io/projects/element-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. **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. Pull Request containing change(s) on the translation files cannot be merged.
#### Adding new string #### Adding new string
When adding new string resources, please only add new entries in the file `value/strings.xml`. Translations will be added later by the community of translators using Weblate. When adding new string resources, please only add new entries in the file `values/strings.xml` ([this file](./library/ui-strings/src/main/res/values/strings.xml)). Translations will be added later by the community of translators using Weblate.
The file `value/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings. The file `values/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings.
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. New strings can be added anywhere in the file `values/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. ##### Plurals
Please use `plurals` resources when appropriate, and note that some languages have specific rules for `plurals`, so even if the string will always be at the plural form for English, please always create a `plurals` resource.
Specific plural forms can be found [here](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html).
#### Editing existing strings #### Editing existing strings
@ -150,6 +204,23 @@ And add `tools:ignore="UnusedResources"` to the string, to let lint ignore that
The string will be removed during the next sync with Weblate. The string will be removed during the next sync with Weblate.
#### Renaming string ids
This is possible to rename ids of the String resources, but since translation files cannot be edited, add TODO in the main strings.xml file above the strings you want to rename.
```xml
<!-- TODO Rename id to put_new_id_here -->
<string name="current_id">Hello Matrix world!</string>
```
The string id(s) will be renamed during the next Weblate sync.
#### Reordering strings
To group strings per feature, or for any other reasons, it is possible to reorder string resources, but only in the [main strings.xml file](./library/ui-strings/src/main/res/values/strings.xml). ). We do not mind about ordering in the translation files, and anyway this is forbidden to edit manually the translation files.
It is also possible to add empty lines between string resources, and to add XML comments. Please note that the XML comment just above a String resource will also appear on Weblate and be visible to the translators.
### Accessibility ### 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_`. 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_`.

View file

@ -1,29 +1,30 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
CFPropertyList (3.0.3) CFPropertyList (3.0.5)
rexml
addressable (2.8.0) addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15) artifactory (3.0.15)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.1.1) aws-eventstream (1.2.0)
aws-partitions (1.479.0) aws-partitions (1.619.0)
aws-sdk-core (3.117.0) aws-sdk-core (3.132.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0) aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
jmespath (~> 1.0) jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.44.0) aws-sdk-kms (1.58.0)
aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.96.1) aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.4)
aws-sigv4 (1.2.4) aws-sigv4 (1.5.1)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4) babosa (1.0.4)
claide (1.0.3) claide (1.1.0)
claide-plugins (0.9.2) claide-plugins (0.9.2)
cork cork
nap nap
@ -48,22 +49,24 @@ GEM
octokit (~> 4.7) octokit (~> 4.7)
terminal-table (>= 1, < 4) terminal-table (>= 1, < 4)
declarative (0.0.20) declarative (0.0.20)
digest-crc (0.6.3) digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0) rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6) dotenv (2.8.1)
emoji_regex (3.2.2) emoji_regex (3.2.3)
excon (0.85.0) excon (0.92.4)
faraday (1.5.1) faraday (1.10.1)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0) faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1) faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1) faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0) faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1) faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0) faraday-patron (~> 1.0)
multipart-post (>= 1.2, < 3) faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4) ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7) faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0) faraday (>= 0.8.0)
@ -71,18 +74,22 @@ GEM
faraday-em_http (1.0.0) faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0) faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0) faraday-excon (1.1.0)
faraday-http-cache (2.4.0) faraday-http-cache (2.4.1)
faraday (>= 0.8) faraday (>= 0.8)
faraday-httpclient (1.0.1) faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1) faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0) faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0) faraday-patron (1.0.0)
faraday_middleware (1.0.0) faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0) faraday (~> 1.0)
fastimage (2.2.4) fastimage (2.2.6)
fastlane (2.187.0) fastlane (2.209.0)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0) addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0) artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0) aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0) babosa (>= 1.0.3, < 2.0.0)
@ -97,7 +104,7 @@ GEM
faraday_middleware (~> 1.0) faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0) fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0) gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.1) google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1) google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31) google-cloud-storage (~> 1.31)
highline (~> 2.0) highline (~> 2.0)
@ -106,6 +113,7 @@ GEM
mini_magick (>= 4.9.4, < 5.0.0) mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0) multipart-post (~> 2.0.0)
naturally (~> 2.2) naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0) plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0) rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3) security (= 0.1.3)
@ -121,9 +129,9 @@ GEM
gh_inspector (1.1.3) gh_inspector (1.1.3)
git (1.11.0) git (1.11.0)
rchardet (~> 1.8) rchardet (~> 1.8)
google-apis-androidpublisher_v3 (0.8.0) google-apis-androidpublisher_v3 (0.25.0)
google-apis-core (>= 0.4, < 2.a) google-apis-core (>= 0.7, < 2.a)
google-apis-core (0.4.0) google-apis-core (0.7.0)
addressable (~> 2.5, >= 2.5.1) addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a) httpclient (>= 2.8.1, < 3.a)
@ -132,47 +140,47 @@ GEM
retriable (>= 2.0, < 4.a) retriable (>= 2.0, < 4.a)
rexml rexml
webrick webrick
google-apis-iamcredentials_v1 (0.6.0) google-apis-iamcredentials_v1 (0.13.0)
google-apis-core (>= 0.4, < 2.a) google-apis-core (>= 0.7, < 2.a)
google-apis-playcustomapp_v1 (0.5.0) google-apis-playcustomapp_v1 (0.10.0)
google-apis-core (>= 0.4, < 2.a) google-apis-core (>= 0.7, < 2.a)
google-apis-storage_v1 (0.6.0) google-apis-storage_v1 (0.17.0)
google-apis-core (>= 0.4, < 2.a) google-apis-core (>= 0.7, < 2.a)
google-cloud-core (1.6.0) google-cloud-core (1.6.0)
google-cloud-env (~> 1.0) google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0) google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 2.0) faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.1.0) google-cloud-errors (1.2.0)
google-cloud-storage (1.34.1) google-cloud-storage (1.38.0)
addressable (~> 2.5) addressable (~> 2.8)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1) google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1) google-apis-storage_v1 (~> 0.17.0)
google-cloud-core (~> 1.6) google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (0.16.2) googleauth (1.2.0)
faraday (>= 0.17.3, < 2.0) faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16) memoist (~> 0.16)
multi_json (~> 1.11) multi_json (~> 1.11)
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (~> 0.14) signet (>= 0.16, < 2.a)
highline (2.0.3) highline (2.0.3)
http-cookie (1.0.4) http-cookie (1.0.5)
domain_name (~> 0.5) domain_name (~> 0.5)
httpclient (2.8.3) httpclient (2.8.3)
jmespath (1.4.0) jmespath (1.6.1)
json (2.5.1) json (2.6.2)
jwt (2.2.3) jwt (2.4.1)
kramdown (2.4.0) kramdown (2.4.0)
rexml rexml
kramdown-parser-gfm (1.1.0) kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0) kramdown (~> 2.0)
memoist (0.16.2) memoist (0.16.2)
mini_magick (4.11.0) mini_magick (4.11.0)
mini_mime (1.1.0) mini_mime (1.1.2)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.0.0) multipart-post (2.0.0)
nanaimo (0.3.0) nanaimo (0.3.0)
@ -183,12 +191,13 @@ GEM
faraday (>= 1, < 3) faraday (>= 1, < 3)
sawyer (~> 0.9) sawyer (~> 0.9)
open4 (1.3.4) open4 (1.3.4)
os (1.1.1) optparse (0.1.1)
os (1.1.4)
plist (3.6.0) plist (3.6.0)
public_suffix (4.0.6) public_suffix (4.0.7)
rake (13.0.6) rake (13.0.6)
rchardet (1.8.0) rchardet (1.8.0)
representable (3.1.1) representable (3.2.0)
declarative (< 0.1.0) declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0) trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0) uber (< 0.2.0)
@ -201,9 +210,9 @@ GEM
addressable (>= 2.3.5) addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3) faraday (>= 0.17.3, < 3)
security (0.1.3) security (0.1.3)
signet (0.15.0) signet (0.17.0)
addressable (~> 2.3) addressable (~> 2.8)
faraday (>= 0.17.3, < 2.0) faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0) jwt (>= 1.5, < 3.0)
multi_json (~> 1.10) multi_json (~> 1.10)
simctl (1.6.8) simctl (1.6.8)
@ -212,7 +221,7 @@ GEM
terminal-notifier (2.0.0) terminal-notifier (2.0.0)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.1) trailblazer-option (0.1.2)
tty-cursor (0.7.1) tty-cursor (0.7.1)
tty-screen (0.8.1) tty-screen (0.8.1)
tty-spinner (0.9.3) tty-spinner (0.9.3)
@ -220,11 +229,11 @@ GEM
uber (0.1.0) uber (0.1.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.7) unf_ext (0.0.8.2)
unicode-display_width (1.7.0) unicode-display_width (1.8.0)
webrick (1.7.0) webrick (1.7.0)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.20.0) xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)
@ -239,6 +248,7 @@ GEM
PLATFORMS PLATFORMS
universal-darwin-21 universal-darwin-21
x86_64-darwin-20 x86_64-darwin-20
x86_64-linux
DEPENDENCIES DEPENDENCIES
danger danger

View file

@ -1,4 +1,4 @@
[![Buildkite](https://badge.buildkite.com/ad0065c1b70f557cd3b1d3d68f9c2154010f83c4d6f71706a9.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop) [![Latest build](https://github.com/vector-im/element-android/actions/workflows/build.yml/badge.svg?query=branch%3Adevelop)](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop)
[![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget) [![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget)
[![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org) [![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
@ -14,7 +14,7 @@ It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-androi
[<img src="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.app) [<img src="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.app)
[<img src="resources/img/f-droid-badge.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.app) [<img src="resources/img/f-droid-badge.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.app)
Nightly build: [![Buildkite](https://badge.buildkite.com/ad0065c1b70f557cd3b1d3d68f9c2154010f83c4d6f71706a9.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop) Nightly test status: [![allScreensTest](https://github.com/vector-im/element-android/actions/workflows/nightly.yml/badge.svg)](https://github.com/vector-im/element-android/actions/workflows/nightly.yml) Build of develop branch: [![GitHub Action](https://github.com/vector-im/element-android/actions/workflows/build.yml/badge.svg?query=branch%3Adevelop)](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop) Nightly test status: [![allScreensTest](https://github.com/vector-im/element-android/actions/workflows/nightly.yml/badge.svg)](https://github.com/vector-im/element-android/actions/workflows/nightly.yml)
# New Android SDK # New Android SDK
@ -40,14 +40,16 @@ If you would like to receive releases more quickly (bearing in mind that they ma
1. [Sign up to receive beta releases](https://play.google.com/apps/testing/im.vector.app) via the Google Play Store. 1. [Sign up to receive beta releases](https://play.google.com/apps/testing/im.vector.app) via the Google Play Store.
2. Install a [release APK](https://github.com/vector-im/element-android/releases) directly - download the relevant .apk file and allow installing from untrusted sources in your device settings. Note: these releases are the Google Play version, which depend on some Google services. If you prefer to avoid that, try the latest dev builds, and choose the F-Droid version. 2. Install a [release APK](https://github.com/vector-im/element-android/releases) directly - download the relevant .apk file and allow installing from untrusted sources in your device settings. Note: these releases are the Google Play version, which depend on some Google services. If you prefer to avoid that, try the latest dev builds, and choose the F-Droid version.
3. If you're really brave, install the [very latest dev build](https://buildkite.com/matrix-dot-org/element-android/builds/latest?branch=develop&state=passed) - click on *Assemble (GPlay or FDroid) Debug version* then on *Artifacts*. 3. If you're really brave, install the [very latest dev build](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop) - pick a build, then click on `Summary` to download the APKs from there: `vector-Fdroid-debug` and `vector-Gplay-debug` contains the APK for the desired store. Each file contains 5 APKs. 4 APKs for every supported specific architecture of device. In doubt you can install the `universal` APK.
## Contributing ## Contributing
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects! Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org). Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org).
Also [this documentation](./docs/_developer_onboarding.md) can hopefully help developers to start working on the project.
## Triaging issues ## Triaging issues
Issues are triaged by community members and the Android App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process). Issues are triaged by community members and the Android App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process).

View file

@ -24,14 +24,16 @@ buildscript {
classpath libs.gradle.gradlePlugin classpath libs.gradle.gradlePlugin
classpath libs.gradle.kotlinPlugin classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin classpath libs.gradle.hiltPlugin
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.2' classpath 'com.google.firebase:firebase-appdistribution-gradle:3.1.1'
classpath 'com.google.gms:google-services:4.3.13' classpath 'com.google.gms:google-services:4.3.14'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.5.0.2730'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
classpath "com.likethesalad.android:stem-plugin:2.1.1" classpath "com.likethesalad.android:stem-plugin:2.2.3"
classpath 'org.owasp:dependency-check-gradle:7.1.1' classpath 'org.owasp:dependency-check-gradle:7.4.1'
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10" classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.20"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
classpath libs.squareup.paparazziPlugin
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
@ -39,12 +41,16 @@ buildscript {
plugins { plugins {
// ktlint Plugin // ktlint Plugin
id "org.jlleitschuh.gradle.ktlint" version "10.3.0" id "org.jlleitschuh.gradle.ktlint" version "11.0.0"
// Detekt // Detekt
id "io.gitlab.arturbosch.detekt" version "1.21.0" id "io.gitlab.arturbosch.detekt" version "1.22.0"
// Ksp
id "com.google.devtools.ksp" version "1.7.22-1.0.8"
// Dependency Analysis // Dependency Analysis
id 'com.autonomousapps.dependency-analysis' version "1.11.2" id 'com.autonomousapps.dependency-analysis' version "1.17.0"
// Gradle doctor
id "com.osacky.doctor" version "0.8.1"
} }
// https://github.com/jeremylong/DependencyCheck // https://github.com/jeremylong/DependencyCheck
@ -57,6 +63,9 @@ dependencyCheck {
] ]
} }
// Gradle doctor configuration
apply from: './tools/gradle/doctor.gradle'
allprojects { allprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint" apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: "io.gitlab.arturbosch.detekt" apply plugin: "io.gitlab.arturbosch.detekt"
@ -70,6 +79,14 @@ allprojects {
groups.mavenCentral.group.each { includeGroup it } groups.mavenCentral.group.each { includeGroup it }
} }
} }
// snapshots repository
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
content {
groups.snapshot.regex.each { includeGroupByRegex it }
groups.snapshot.group.each { includeGroup it }
}
}
maven { maven {
url 'https://jitpack.io' url 'https://jitpack.io'
content { content {
@ -79,9 +96,9 @@ allprojects {
} }
// Jitsi repo // Jitsi repo
maven { maven {
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-5.0.2" url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-6.2.2"
// Note: to test Jitsi release you can use a local file like this: // Note: to test Jitsi release you can use a local file like this:
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-3.10.0" // url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-6.2.2"
content { content {
groups.jitsi.regex.each { includeGroupByRegex it } groups.jitsi.regex.each { includeGroupByRegex it }
groups.jitsi.group.each { includeGroup it } groups.jitsi.group.each { includeGroup it }
@ -131,6 +148,9 @@ allprojects {
// To have XML report for Danger // To have XML report for Danger
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE) reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
} }
filter {
exclude { element -> element.file.path.contains("$buildDir/generated/") }
}
disabledRules = [ disabledRules = [
// TODO Re-enable these 4 rules after reformatting project // TODO Re-enable these 4 rules after reformatting project
"indent", "indent",
@ -151,6 +171,8 @@ allprojects {
"experimental:comment-wrapping", "experimental:comment-wrapping",
// - A KDoc comment after any other element on the same line must be separated by a new line // - A KDoc comment after any other element on the same line must be separated by a new line
"experimental:kdoc-wrapping", "experimental:kdoc-wrapping",
// Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt"
"string-template",
] ]
} }
@ -213,7 +235,7 @@ project(":vector") {
} }
} }
project(":library:diff-match-patch") { project(":library:external:diff-match-patch") {
sonarqube { sonarqube {
skipProject = true skipProject = true
} }
@ -284,3 +306,61 @@ dependencyAnalysis {
} }
} }
} }
tasks.register("recordScreenshots", GradleBuild) {
startParameter.projectProperties.screenshot = ""
tasks = [':vector:recordPaparazziDebug']
}
tasks.register("verifyScreenshots", GradleBuild) {
startParameter.projectProperties.screenshot = ""
tasks = [':vector:verifyPaparazziDebug']
}
ext.initScreenshotTests = { project ->
def hasScreenshots = project.hasProperty("screenshot")
if (hasScreenshots) {
project.apply plugin: 'app.cash.paparazzi'
}
project.dependencies { testCompileOnly libs.squareup.paparazzi }
project.android.testOptions.unitTests.all {
def screenshotTestCapture = "**/*ScreenshotTest*"
if (hasScreenshots) {
include screenshotTestCapture
} else {
exclude screenshotTestCapture
}
}
}
// Workaround to have KSP generated Kotlin code available in the IDE (for code completion)
// Ref: https://github.com/airbnb/epoxy/releases/tag/5.0.0beta02
subprojects { project ->
afterEvaluate {
if (project.hasProperty("android")) {
android {
if (it instanceof com.android.build.gradle.LibraryExtension) {
libraryVariants.all { variant ->
def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
if (outputFolder.exists()) {
variant.addJavaSourceFoldersToModel(outputFolder)
android.sourceSets.getAt(variant.name).java {
srcDir(outputFolder)
}
}
}
} else if (it instanceof com.android.build.gradle.AppExtension) {
applicationVariants.all { variant ->
def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
if (outputFolder.exists()) {
variant.addJavaSourceFoldersToModel(outputFolder)
android.sourceSets.getAt(variant.name).java {
srcDir(outputFolder)
}
}
}
}
}
}
}
}

1
changelog.d/5546.bugfix Normal file
View file

@ -0,0 +1 @@
ReplyTo are not updated if the original message is edited or deleted.

View file

@ -1 +0,0 @@
added filter tabs for new App layout's Home screen

View file

@ -1 +0,0 @@
Adds New App Layout FABs (hidden behind feature flag)

View file

@ -1 +0,0 @@
[Notification] - Handle creation of notification for live location and poll start

View file

@ -1 +0,0 @@
Decouples the variant logic from the vector module

View file

@ -1 +0,0 @@
Add a developer setting to enable LeakCanary at runtime

View file

@ -1 +0,0 @@
[Devices management] Add a feature flag and empty screen for future new layout

View file

@ -1 +0,0 @@
[Create Room] Reduce some boilerplate with room state event contents

View file

@ -1 +0,0 @@
[Call] Memory leak after a call

1
changelog.d/7853.bugfix Normal file
View file

@ -0,0 +1 @@
[Session manager] Missing info when a session does not support encryption

1
changelog.d/7887.feature Normal file
View file

@ -0,0 +1 @@
"[Rich text editor] Add list formatting buttons to the rich text editor"

View file

@ -28,8 +28,8 @@ def initializeReport(report, projects, classExcludes) {
report.executionData { report.executionData {
fileTree(rootProject.rootDir.absolutePath).include( fileTree(rootProject.rootDir.absolutePath).include(
"**/build/**/*.exec", "**/build/**/*.exec",
"**/build/outputs/code_coverage/**/coverage.ec", "**/build/outputs/code_coverage/**/coverage.ec",
) )
} }
report.reports { report.reports {
@ -74,18 +74,18 @@ def collectProjects(predicate) {
task generateCoverageReport(type: JacocoReport) { task generateCoverageReport(type: JacocoReport) {
outputs.upToDateWhen { false } outputs.upToDateWhen { false }
rootProject.apply plugin: 'jacoco' rootProject.apply plugin: 'jacoco'
def projects = collectProjects { ['vector', 'matrix-sdk-android'].contains(it.name) } def projects = collectProjects { ['vector-app', 'vector', 'matrix-sdk-android'].contains(it.name) }
initializeReport(it, projects, excludes) initializeReport(it, projects, excludes)
} }
task unitTestsWithCoverage(type: GradleBuild) { task unitTestsWithCoverage(type: GradleBuild) {
// the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage // the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage
startParameter.projectProperties.coverage = [enableTestCoverage: false] startParameter.projectProperties.coverage = [enableTestCoverage: false]
tasks = [':vector:testGplayDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest'] tasks = ['testDebugUnitTest']
} }
task instrumentationTestsWithCoverage(type: GradleBuild) { task instrumentationTestsWithCoverage(type: GradleBuild) {
startParameter.projectProperties.coverage = [enableTestCoverage: true] startParameter.projectProperties.coverage = [enableTestCoverage: true]
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui' startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
tasks = [':vector:connectedGplayDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest'] tasks = [':vector-app:connectedGplayDebugAndroidTest', ':vector:connectedDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest']
} }

View file

@ -1,48 +1,46 @@
ext.versions = [ ext.versions = [
'minSdk' : 21, 'minSdk' : 21,
'compileSdk' : 31, 'compileSdk' : 33,
'targetSdk' : 31, 'targetSdk' : 33,
'sourceCompat' : JavaVersion.VERSION_11, 'sourceCompat' : JavaVersion.VERSION_11,
'targetCompat' : JavaVersion.VERSION_11, 'targetCompat' : JavaVersion.VERSION_11,
] ]
def gradle = "7.3.1"
// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142
// Please test carefully before upgrading again.
def gradle = "7.1.3"
// Ref: https://kotlinlang.org/releases.html // Ref: https://kotlinlang.org/releases.html
def kotlin = "1.6.21" def kotlin = "1.7.22"
def kotlinCoroutines = "1.6.4" def kotlinCoroutines = "1.6.4"
def dagger = "2.42" def dagger = "2.44.2"
def appDistribution = "16.0.0-beta03" def firebaseBom = "31.1.1"
def appDistribution = "16.0.0-beta05"
def retrofit = "2.9.0" def retrofit = "2.9.0"
def arrow = "0.8.2"
def markwon = "4.6.2" def markwon = "4.6.2"
def moshi = "1.13.0" def moshi = "1.14.0"
def lifecycle = "2.5.1" def lifecycle = "2.5.1"
def flowBinding = "1.2.0" def flowBinding = "1.2.0"
def flipper = "0.156.0" def flipper = "0.176.0"
def epoxy = "4.6.2" def epoxy = "5.0.0"
def mavericks = "2.7.0" def mavericks = "3.0.1"
def glide = "4.13.2" def glide = "4.14.2"
def bigImageViewer = "1.8.1" def bigImageViewer = "1.8.1"
def jjwt = "0.11.5" def jjwt = "0.11.5"
def vanniktechEmoji = "0.15.0" // Temporary version to unblock #6929. Once 0.16.0 is released we should use it, and revert
// the whole commit which set version 0.16.0-SNAPSHOT
def fragment = "1.5.1" def vanniktechEmoji = "0.16.0-SNAPSHOT"
def sentry = "6.9.2"
def fragment = "1.5.5"
// Testing // Testing
def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819 def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
def espresso = "3.4.0" def espresso = "3.4.0"
def androidxTest = "1.4.0" def androidxTest = "1.4.0"
def androidxOrchestrator = "1.4.1" def androidxOrchestrator = "1.4.2"
def paparazzi = "1.1.0"
ext.libs = [ ext.libs = [
gradle : [ gradle : [
'gradlePlugin' : "com.android.tools.build:gradle:$gradle", 'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin", 'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin",
'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger" 'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger"
], ],
jetbrains : [ jetbrains : [
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines", 'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
@ -50,12 +48,12 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines" 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
], ],
androidx : [ androidx : [
'activity' : "androidx.activity:activity:1.5.1", 'activity' : "androidx.activity:activity-ktx:1.6.1",
'appCompat' : "androidx.appcompat:appcompat:1.4.2", 'appCompat' : "androidx.appcompat:appcompat:1.5.1",
'biometric' : "androidx.biometric:biometric:1.1.0", 'biometric' : "androidx.biometric:biometric:1.1.0",
'core' : "androidx.core:core-ktx:1.8.0", 'core' : "androidx.core:core-ktx:1.9.0",
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1", 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3", 'exifinterface' : "androidx.exifinterface:exifinterface:1.3.5",
'fragmentKtx' : "androidx.fragment:fragment-ktx:$fragment", 'fragmentKtx' : "androidx.fragment:fragment-ktx:$fragment",
'fragmentTesting' : "androidx.fragment:fragment-testing:$fragment", 'fragmentTesting' : "androidx.fragment:fragment-testing:$fragment",
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4", 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4",
@ -82,9 +80,13 @@ ext.libs = [
'transition' : "androidx.transition:transition:1.2.0", 'transition' : "androidx.transition:transition:1.2.0",
], ],
google : [ google : [
'material' : "com.google.android.material:material:1.6.1", 'material' : "com.google.android.material:material:1.7.0",
'firebaseBom' : "com.google.firebase:firebase-bom:$firebaseBom",
'messaging' : "com.google.firebase:firebase-messaging",
'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution", 'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution",
'appdistribution' : "com.google.firebase:firebase-appdistribution:$appDistribution", 'appdistribution' : "com.google.firebase:firebase-appdistribution:$appDistribution",
// Phone number https://github.com/google/libphonenumber
'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.13.3"
], ],
dagger : [ dagger : [
'dagger' : "com.google.dagger:dagger:$dagger", 'dagger' : "com.google.dagger:dagger:$dagger",
@ -98,25 +100,26 @@ ext.libs = [
'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper",
], ],
element : [ element : [
'opusencoder' : "io.element.android:opusencoder:1.0.4", 'opusencoder' : "io.element.android:opusencoder:1.1.0",
'wysiwyg' : "io.element.android:wysiwyg:0.13.0"
], ],
squareup : [ squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi", 'moshi' : "com.squareup.moshi:moshi:$moshi",
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi", 'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi", 'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
'moshiAdapters' : "com.squareup.moshi:moshi-adapters:$moshi",
'paparazzi' : "app.cash.paparazzi:paparazzi:$paparazzi",
'paparazziPlugin' : "app.cash.paparazzi:paparazzi-gradle-plugin:$paparazzi",
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit", 'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit" 'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
], ],
rx : [ rx : [
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0" 'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0"
], ],
arrow : [
'core' : "io.arrow-kt:arrow-core:$arrow",
'instances' : "io.arrow-kt:arrow-instances-core:$arrow"
],
markwon : [ markwon : [
'core' : "io.noties.markwon:core:$markwon", 'core' : "io.noties.markwon:core:$markwon",
'extLatex' : "io.noties.markwon:ext-latex:$markwon", 'extLatex' : "io.noties.markwon:ext-latex:$markwon",
'imageGlide' : "io.noties.markwon:image-glide:$markwon",
'inlineParser' : "io.noties.markwon:inline-parser:$markwon", 'inlineParser' : "io.noties.markwon:inline-parser:$markwon",
'html' : "io.noties.markwon:html:$markwon" 'html' : "io.noties.markwon:html:$markwon"
], ],
@ -129,7 +132,7 @@ ext.libs = [
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks" 'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
], ],
maplibre : [ maplibre : [
'androidSdk' : "org.maplibre.gl:android-sdk:9.5.2", 'androidSdk' : "org.maplibre.gl:android-sdk:9.6.0",
'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0" 'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0"
], ],
mockk : [ mockk : [
@ -160,12 +163,15 @@ ext.libs = [
'emojiGoogle' : "com.vanniktech:emoji-google:$vanniktechEmoji" 'emojiGoogle' : "com.vanniktech:emoji-google:$vanniktechEmoji"
], ],
apache : [ apache : [
'commonsImaging' : "org.apache.sanselan:sanselan:0.97-incubator" 'commonsImaging' : "org.apache.commons:commons-imaging:1.0-alpha3"
],
sentry: [
'sentryAndroid' : "io.sentry:sentry-android:$sentry"
], ],
tests : [ tests : [
'kluent' : "org.amshove.kluent:kluent-android:1.68", 'kluent' : "org.amshove.kluent:kluent-android:1.72",
'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1", 'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1",
'junit' : "junit:junit:4.13.2" 'junit' : "junit:junit:4.13.2",
] ]
] ]

View file

@ -38,10 +38,18 @@ ext.groups = [
'com.google.testing.platform', 'com.google.testing.platform',
] ]
], ],
snapshot: [
regex: [
],
group: [
'com.vanniktech',
]
],
mavenCentral: [ mavenCentral: [
regex: [ regex: [
], ],
group: [ group: [
'app.cash.paparazzi',
'ch.qos.logback', 'ch.qos.logback',
'com.adevinta.android', 'com.adevinta.android',
'com.airbnb.android', 'com.airbnb.android',
@ -69,8 +77,6 @@ ext.groups = [
'com.gabrielittner.threetenbp', 'com.gabrielittner.threetenbp',
'com.getkeepsafe.relinker', 'com.getkeepsafe.relinker',
'com.github.bumptech.glide', 'com.github.bumptech.glide',
'com.github.filippudak',
'com.github.filippudak.progresspieview',
'com.github.javaparser', 'com.github.javaparser',
'com.github.piasy', 'com.github.piasy',
'com.github.shyiko.klob', 'com.github.shyiko.klob',
@ -78,6 +84,7 @@ ext.groups = [
'com.google', 'com.google',
'com.google.android', 'com.google.android',
'com.google.api.grpc', 'com.google.api.grpc',
'com.google.auto',
'com.google.auto.service', 'com.google.auto.service',
'com.google.auto.value', 'com.google.auto.value',
'com.google.code.findbugs', 'com.google.code.findbugs',
@ -95,6 +102,7 @@ ext.groups = [
'com.googlecode.json-simple', 'com.googlecode.json-simple',
'com.googlecode.libphonenumber', 'com.googlecode.libphonenumber',
'com.ibm.icu', 'com.ibm.icu',
'com.intellij',
'com.jakewharton.android.repackaged', 'com.jakewharton.android.repackaged',
'com.jakewharton.timber', 'com.jakewharton.timber',
'com.kgurgul.flipper', 'com.kgurgul.flipper',
@ -120,13 +128,12 @@ ext.groups = [
'com.sun.xml.bind.mvn', 'com.sun.xml.bind.mvn',
'com.sun.xml.fastinfoset', 'com.sun.xml.fastinfoset',
'com.thoughtworks.qdox', 'com.thoughtworks.qdox',
'com.vanniktech', // 'com.vanniktech',
'commons-cli', 'commons-cli',
'commons-codec', 'commons-codec',
'commons-io', 'commons-io',
'commons-logging', 'commons-logging',
'info.picocli', 'info.picocli',
'io.arrow-kt',
'io.element.android', 'io.element.android',
'io.github.davidburstrom.contester', 'io.github.davidburstrom.contester',
'io.github.detekt.sarif4k', 'io.github.detekt.sarif4k',
@ -140,16 +147,21 @@ ext.groups = [
'io.netty', 'io.netty',
'io.noties.markwon', 'io.noties.markwon',
'io.opencensus', 'io.opencensus',
'io.perfmark',
'io.reactivex.rxjava2', 'io.reactivex.rxjava2',
'io.realm', 'io.realm',
'io.sentry',
'it.unimi.dsi', 'it.unimi.dsi',
'jakarta.activation', 'jakarta.activation',
'jakarta.xml.bind', 'jakarta.xml.bind',
'javax.activation',
'javax.annotation', 'javax.annotation',
'javax.inject', 'javax.inject',
'javax.xml.bind',
'jline', 'jline',
'jp.wasabeef', 'jp.wasabeef',
'junit', 'junit',
'kxml2',
'me.saket', 'me.saket',
'net.bytebuddy', 'net.bytebuddy',
'net.java', 'net.java',
@ -164,8 +176,8 @@ ext.groups = [
'org.apache.ant', 'org.apache.ant',
'org.apache.commons', 'org.apache.commons',
'org.apache.httpcomponents', 'org.apache.httpcomponents',
'org.apache.sanselan',
'org.bouncycastle', 'org.bouncycastle',
'org.ccil.cowan.tagsoup',
'org.checkerframework', 'org.checkerframework',
'org.codehaus', 'org.codehaus',
'org.codehaus.groovy', 'org.codehaus.groovy',
@ -178,11 +190,13 @@ ext.groups = [
'org.hamcrest', 'org.hamcrest',
'org.jacoco', 'org.jacoco',
'org.java-websocket', 'org.java-websocket',
'org.jcodec',
'org.jetbrains', 'org.jetbrains',
'org.jetbrains.dokka', 'org.jetbrains.dokka',
'org.jetbrains.intellij.deps', 'org.jetbrains.intellij.deps',
'org.jetbrains.kotlin', 'org.jetbrains.kotlin',
'org.jetbrains.kotlinx', 'org.jetbrains.kotlinx',
'org.jetbrains.trove4j',
'org.json', 'org.json',
'org.jsoup', 'org.jsoup',
'org.junit', 'org.junit',
@ -199,7 +213,6 @@ ext.groups = [
'org.ow2.asm', 'org.ow2.asm',
'org.ow2.asm', 'org.ow2.asm',
'org.reactivestreams', 'org.reactivestreams',
'org.robolectric',
'org.slf4j', 'org.slf4j',
'org.sonatype.oss', 'org.sonatype.oss',
'org.testng', 'org.testng',

View file

@ -0,0 +1,259 @@
# Developer on boarding
<!--- TOC -->
* [Introduction](#introduction)
* [Quick introduction to Matrix](#quick-introduction-to-matrix)
* [Matrix data](#matrix-data)
* [Room](#room)
* [Event](#event)
* [Sync](#sync)
* [Glossary about syncs](#glossary-about-syncs)
* [The Android project](#the-android-project)
* [Matrix SDK](#matrix-sdk)
* [Application](#application)
* [MvRx](#mvrx)
* [Behavior](#behavior)
* [Epoxy](#epoxy)
* [Other frameworks](#other-frameworks)
* [Push](#push)
* [Dependencies management](#dependencies-management)
* [Test](#test)
* [Other points](#other-points)
* [Logging](#logging)
* [Rageshake](#rageshake)
* [Tips](#tips)
* [Happy coding!](#happy-coding)
<!--- END -->
## Introduction
This doc is a quick introduction about the project and its architecture.
It's aim is to help new developers to understand the overall project and where to start developing.
Other useful documentation:
- all the docs in this folder!
- the [contributing doc](../CONTRIBUTING.md), that you should also read carefully.
### Quick introduction to Matrix
Matrix website: [matrix.org](https://matrix.org), [discover page](https://matrix.org/discover).
*Note*: Matrix.org is also hosting a homeserver ([.well-known file](https://matrix.org/.well-known/matrix/client)).
The reference homeserver (this is how Matrix servers are called) implementation is [Synapse](https://github.com/matrix-org/synapse/). But other implementations exist. The Matrix specification is here to ensure that any Matrix client, such as Element Android and its SDK can talk to any Matrix server.
Have a quick look to the client-server API documentation: [Client-server documentation](https://spec.matrix.org/v1.3/client-server-api/). Other network API exist, the list is here: (https://spec.matrix.org/latest/)
Matrix is an open source protocol. Change are possible and are tracked using [this GitHub repository](https://github.com/matrix-org/matrix-doc/). Changes to the protocol are called MSC: Matrix Spec Change. These are PullRequest to this project.
Matrix object are Json data. Unstable prefixes must be used for Json keys when the MSC is not merged (i.e. accepted).
#### Matrix data
There are many object and data in the Matrix worlds. Let's focus on the most important and used, `Room` and `Event`
##### Room
`Room` is a place which contains ordered `Event`s. They are identified with their `room_id`. Nearly all the data are stored in rooms, and shared using homeserver to all the Room Member.
*Note*: Spaces are also Rooms with a different `type`.
##### Event
`Events` are items of a Room, where data is embedded.
There are 2 types of Room Event:
- Regular Events: contain useful content for the user (message, image, etc.), but are not necessarily displayed as this in the timeline (reaction, message edition, call signaling).
- State Events: contain the state of the Room (name, topic, etc.). They have a non null value for the key `state_key`.
Also all the Room Member details are in State Events: one State Event per member. In this case, the `state_key` is the matrixId (= userId).
Important Fields of an Event:
- `event_id`: unique across the Matrix universe;
- `room_id`: the room the Event belongs to;
- `type`: describe what the Event contain, especially in the `content` section, and how the SDK should handle this Event;
- `content`: dynamic Event data; depends on the `type`.
So we have a triple `event_id`, `type`, `state_key` which uniquely defines an Event.
#### Sync
The `Sync` is a way for the Matrix client to be up to date regarding the user data hosted by the server. All the Events are coming through the sync response. More details can be found here: [spec.matrix.org/v1.3/client-server-api/#syncing](https://spec.matrix.org/v1.3/client-server-api/#syncing)
When the application is in foreground, this is a looping request. We are using Https requests, which offer the advantage to be compatible with any homeserver. A sync token is used as request parameter, to let the server know what the client knows.
The `SyncThread` is responsible to manage the sync request loop.
When the application is in background, a Push will trigger a sync request.
##### Glossary about syncs
- **initial sync**: a sync request without a token. This is the first request a client perform after login or after a clear cache. The server will include in the response all your rooms with the full state (all the room membership Event will not be present), with the latest messages for each room. We are in the process to replace this by version 3: sliding sync. All data are inserted to the Database (currently [Realm](https://www.mongodb.com/docs/realm/sdk/java/)).
- **incremental sync**: sync request with a token.
- **gappy sync**: sync request where all the new Events are not returned for one or several Rooms. Also called `limited sync`. It can be limited per Room. To get all the missing Events, a Room pagination API has to be called.
- **sync token**: `next_batch` value in the previous sync response. Will be provided as the `since` parameter for the next sync request.
### The Android project
The project should compile out of the box.
The project is split into several modules. The main ones are:
For the app
- `vector-app`: application entry point;
- `vector`: legacy application, but now a library. In the process of being split into several modules;
- `vector-config`: this is where all the configuration of the application should occurs. Should because we are in the process of migrating all the configuration here;
- `library/ui-strings`: this is where all the string resources are stored. Please refer to [contributing doc](../CONTRIBUTING.md) to know how to make change on this module;
- `library/ui-styles`: this is where the Android styles are defined.
For the SDK
- `matrix-sdk-android`: the main SDK module. The sources are in this project, but are also exported to [its own project](https://github.com/matrix-org/matrix-android-sdk2). All the PRs and issues related to the SDK take place in the Element Android project;
- `matrix-sdk-android-flow`: contains some wrapper to expose `Flow` to the application.
### Matrix SDK
SDK exposes `Services` to the client application. `Services` are public interface, and are defined in this parent package: `org.matrix.android.sdk.api`. Default implementation are internal to the SDK, in this parent package: `org.matrix.android.sdk.internal`. Note that you also have to declare the classes as `internal` when adding classes to the `org.matrix.android.sdk.internal` package.
Interface allows us to replace the implementation for testing purpose.
A generated documentation of the SDK is available [here](https://matrix-org.github.io/matrix-android-sdk2/). Updated after each release. Please ensure that the documentation (KDoc) of all the SDK Services is up to date, and is clear for a SDK user.
The SDK generated documentation also contains information about the entry points of the SDK.
[Dagger](https://dagger.dev/) is used to inject all the dependencies to the SDK classes.
SDK is exposing data as `LiveData`, but we are progressively migrating to `Flow`. Database is the source of truth.
Example:
- Client send an Event using the `SendService`;
- At the end a `SendEvent` task is used;
- Retrofit API is used to send data to the server;
- Goes to the server, which returns only the `event_id`;
- The `Event` is coming back from the `sync` response with eventually extra added data.
### Application
This is the UI part of the project.
There are two variants of the application: `Gplay` and `Fdroid`.
The main difference is about using Firebase on `Gplay` variant, to have Push from Google Services. `FDroid` variant cannot contain closed source dependency.
`Fdroid` is using background polling to lack the missing of Pushed. Now a solution using UnifiedPush has ben added to the project. See refer to [the dedicated documentation](./unifiedpush.md) for more details.
#### MvRx
[Maverick](https://airbnb.io/mavericks/#/README) (or MvRx) is an Android MVI framework that helps to develop Reactive application on Android.
- Activity: holder for Fragment. See the parent [VectorBaseActivity](../vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt);
- Fragment: manage screen of the application. See the parent [VectorBaseFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt);
- BottomSheet: see the parent [VectorBaseBottomSheetDialogFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt);
- ViewModel: this is where the logic is placed. All our ViewModel has a `handle()` which takes action as parameter. See the parent [VectorViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt);
- VectorSharedActionViewModel: Specific ViewModel that can be used to communicate between Fragment(s) and the host Activity. See the parent [VectorSharedActionViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorSharedActionViewModel.kt);
- ViewState: this are `data class`, and this represent the state of the View. Has to be copied and set to be updated. Fragment will update the UI regarding the current state (`invalidate()` method). `Async` class from MvRx can be used in the ViewState, especially for asynchronous data loading. Nullability can also be used for optional data. ViewStates have to implement `MavericksState`;
- ViewEvents: useful when the ViewModel asks the View to trigger a specific action: navigation, show dialog, etc. See the parent [VectorViewEvents](../vector/src/main/java/im/vector/app/core/platform/VectorViewEvents.kt);
- ViewAction (`VectorViewModelAction`): useful when the UI (generally the Fragment) asks the ViewModel to do something. See the parent [VectorViewModelAction](../vector/src/main/java/im/vector/app/core/platform/VectorViewModelAction.kt);
- Controller: see the `Epoxy` section just below.
##### Behavior
Fragment asks the ViewModel to perform an action (coming from the user, but not necessarily. ViewModel can then talk to the SDK, updates the state once or several times. Fragment update the UI regarding the new state.
When ViewModel is instantiated, it can subscribe using the SDK Services to get live state of the data.
`invalidate()` has to be used by default, but it's possible to listen to specific member(s) of the `ViewState` using `onEach`. TODO Add an example.
`awaitState()` method
#### Epoxy
[Epoxy](https://github.com/airbnb/epoxy) is an Android library for building complex screens in a RecyclerView. Please read [the introduction](https://github.com/airbnb/epoxy#epoxy).
- Controller declares items of the RecyclerView. Controller is injected in the Fragment. Controller extends `EpoxyController`, or one of its subclass, especially `TypedEpoxyController`;
- Fragment gives the state to the controller using `setData`;
- `buildModels` will be called by the framework;
- Controller will create ordered Items.
Epoxy does the diffing, and handle many other thing for us, like handling item type, etc.
See for instance the controller [AccountDataEpoxyController](../vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt)) for a simple example.
Warning: do not use twice the same item `id` or it will crash.
#### Other frameworks
- Dependency injection is managed by [Dagger](https://dagger.dev/) (SDK) and [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) (App);
- [Retrofit](https://square.github.io/retrofit/) and [OkHttp3](https://square.github.io/okhttp/): network requests;
- [Moshi](https://github.com/square/moshi) is used to parse and serialize Json object;
### Push
Please see the dedicated documentation for more details.
This is the classical scenario:
- App receives a Push. Note: Push is ignored if app is in foreground;
- App asks the SDK to load Event data (fastlane mode). We have a change to get the data faster and display the notification faster;
- App asks the SDK to perform a sync request.
### Dependencies management
All the dependencies are declared in `build.gradle` files. But some versions are declared in [this dedicated file](../dependencies.gradle).
When adding a new dependency, you will have to update the file [dependencies_groups.gradle](../dependencies_groups.gradle) to allow the dependency to be downloaded from the artifact repository. Sometimes sub-dependencies need to be added too, until the project can compile.
[Dependabot](https://github.com/dependabot) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one.
dependencies_group, gradle files, Dependabot, etc.
### Test
Please refer to [this dedicated document](./ui-tests.md).
TODO add link to the dedicated screenshot test documentation
### Other points
#### Logging
**Important warning: ** NEVER log private user data, or use the flag `LOG_PRIVATE_DATA`. Be very careful when logging `data class`, all the content will be output!
[Timber](https://github.com/JakeWharton/timber) is used to log data to logcat. We do not use directly the `Log` class. If possible please use a tag, as per
````kotlin
Timber.tag(loggerTag.value).d("my log")
````
because automatic tag (= class name) will not be available on the release version.
Also generally it is recommended to provide the `Throwable` to the Timber log functions.
Last point, not that `Timber.v` function may have no effect on some devices. Prefer using `Timber.d` and up.
#### Rageshake
Rageshake is a feature to send bug report directly from the application. Just shake your phone and you will be prompted to send a bug report.
Bug report can contain:
- a screenshot of the current application state
- the application logs from up to 15 application starts
- the logcat logs
- the key share history (crypto data)
The data will be sent to an internal server, which is not publicly accessible. A GitHub issue will also be created to a private GitHub repository.
Rageshake can be very useful to get logs from a release version of the application.
### Tips
- Element Android has a `developer mode` in the `Settings/Advanced settings`. Other useful options are available here;
- Show hidden Events can also help to debug feature. When developer mode is enabled, it is possible to view the source (= the Json content) of any Events;
- Type `/devtools` in a Room composer to access a developer menu. There are some other entry points. Developer mode has to be enabled;
- Hidden debug menu: when developer mode is enabled and on debug build, there are some extra screens that can be accessible using the green wheel. In those screens, it will be possible to toggle some feature flags;
- Using logcat, filtering with `onResume` can help you to understand what screen are currently displayed on your device. Searching for string displayed on the screen can also help to find the running code in the codebase.
- When this is possible, prefer using `sealed interface` instead of `sealed class`;
- When writing temporary code, using the string "DO NOT COMMIT" in a comment can help to avoid committing things by mistake. If committed and pushed, the CI will detect this String and will warn the user about it.
## Happy coding!
The team is here to support you, feel free to ask anything to other developers.
Also please feel to update this documentation, if incomplete/wrong/obsolete/etc.
**Thanks!**

View file

@ -23,10 +23,12 @@ Here are the checks that Danger does so far:
- PR description is not empty - PR description is not empty
- Big PR got a warning to recommend to split - Big PR got a warning to recommend to split
- PR contains a file for towncrier and extension is checked - PR contains a file for towncrier and extension is checked
- PR does not modify frozen classes
- PR contains a Sign-Off, with exception for Element employee contributors - PR contains a Sign-Off, with exception for Element employee contributors
- PR with change on layout should include screenshot in the description - PR with change on layout should include screenshot in the description
- PR which adds png file warn about the usage of vector drawables - PR which adds png file warn about the usage of vector drawables
- non draft PR should have a reviewer - non draft PR should have a reviewer
- files containing translations are not modified by developers
### Quality check ### Quality check
@ -84,6 +86,8 @@ To let Danger check all the PRs, including PRs form forks, a GitHub account have
- password: Stored on Passbolt - password: Stored on Passbolt
- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret. - GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR.
## Useful links ## Useful links
- https://danger.systems/ - https://danger.systems/

View file

@ -0,0 +1,55 @@
<!--- TOC -->
* [Testing database migration](#testing-database-migration)
* [Creating a reference database](#creating-a-reference-database)
* [Testing](#testing)
<!--- END -->
## Testing database migration
### Creating a reference database
Databases are encrypted, the key to decrypt is needed to setup the test.
A special build property must be enabled to extract it.
Set `vector.debugPrivateData=true` in `~/.gradle/gradle.properties` (to avoid committing by mistake)
Launch the app in your emulator, login and use the app to fill up the database.
Save the key for the tested database
```
RealmKeysUtils W Database key for alias `session_db_fe9f212a611ccf6dea1141777065ed0a`: 935a6dfa0b0fc5cce1414194ed190....
RealmKeysUtils W Database key for alias `crypto_module_fe9f212a611ccf6dea1141777065ed0a`: 7b9a21a8a311e85d75b069a343.....
```
Use the [Device File Explorer](https://developer.android.com/studio/debug/device-file-explorer) to extrat the database file from the emulator.
Go to `data/data/im.vector.app.debug/files/<hash>/`
Pick the database you want to test (name can be found in SessionRealmConfigurationFactory):
- crypto_store.realm for crypto
- disk_store.realm for session
- etc...
Download the file on your disk
### Testing
Copy the file in `src/AndroidTest/assets`
see `CryptoSanityMigrationTest` or `RealmSessionStoreMigration43Test` for sample tests.
There are already some databases in the assets folder.
The existing test will properly detect schema changes, and fail with such errors if a migration is missing:
```
io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:
- Property 'CryptoMetadataEntity.foo' has been added.
```
If you want to test properly more complex database migration (dynamic transforms) ensure that the database contains
the entity you want to migrate.
You can explore the database with [realm studio](https://www.mongodb.com/docs/realm/studio/) if needed.

View file

@ -7,8 +7,8 @@ Hilt is built on top of Dagger 2 and simplify usage by removing needs to create
When you create a new feature, you should have the following: When you create a new feature, you should have the following:
Annotate your Activity with @AndroidEntryPoint Annotate your Activity with @AndroidEntryPoint
Annotate your Fragment with @AndroidEntryPoint
If you have a BottomSheetFragment => Annotate it 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 Add your ViewModel.Factory to the MavericksViewModelModule
Makes sure your ViewModel as the following code: Makes sure your ViewModel as the following code:

View file

@ -0,0 +1,52 @@
## Installing from CI
<!--- TOC -->
* [Installing from Buildkite](#installing-from-buildkite)
* [Installing from GitHub](#installing-from-github)
* [Create a GitHub token](#create-a-github-token)
* [Provide artifact URL](#provide-artifact-url)
* [Next steps](#next-steps)
* [Future improvement](#future-improvement)
<!--- END -->
Installing APK build by the CI is possible
### Installing from Buildkite
The script `./tools/install/installFromBuildkite.sh` can be used, but Builkite will be removed soon. See next section.
### Installing from GitHub
To install an APK built by a GitHub action, run the script `./tools/install/installFromGitHub.sh`. You will need to pass a GitHub token to do so.
#### Create a GitHub token
You can create a GitHub token going to your Github account, at this page: [https://github.com/settings/tokens](https://github.com/settings/tokens).
You need to create a token (classic) with the scope `repo/public_repo`. So just check the corresponding checkbox.
Validity can be long since the scope of this token is limited. You will still be able to delete the token and generate a new one.
Click on Generate token and save the token locally.
### Provide artifact URL
The script will ask for an artifact URL. You can get this artifact URL by following these steps:
- open the pull request
- in the check at the bottom, click on `APK Build / Build debug APKs`
- click on `Summary`
- scroll to the bottom of the page
- copy the link `vector-Fdroid-debug` if you want the F-Droid variant or `vector-Gplay-debug` if you want the Gplay variant.
The copied link can be provided to the script.
### Next steps
The script will download the artifact, unzip it and install the correct version (regarding arch) on your device.
Files will be added to the folder `./tmp/DebugApks`. Feel free to cleanup this folder from time to time, the script will not delete files.
### Future improvement
The script could ask the user for a Pull Request number and Gplay/Fdroid choice like it was done with Buildkite script. Using GitHub API may be possible to do that.

View file

@ -93,4 +93,4 @@ url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-3.10.
- Build the project and perform the sanity tests again. - Build the project and perform the sanity tests again.
- Update the file `/CHANGES.md` to notify about the library upgrade, and create a regular PR for project Element Android. - Create a PR for project Element Android and add a changelog file `<PR_NUMBER>.misc` to notify about the library upgrade.

View file

@ -47,7 +47,7 @@ git checkout develop
mv towncrier.toml towncrier.toml.bak mv towncrier.toml towncrier.toml.bak
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
rm towncrier.toml.bak rm towncrier.toml.bak
yes n | towncrier --version nightly yes n | towncrier build --version nightly
./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES
``` ```

View file

@ -0,0 +1,72 @@
# Screenshot testing
<!--- TOC -->
* [Overview](#overview)
* [Setup](#setup)
* [Recording](#recording)
* [Verifying](#verifying)
* [Contributing](#contributing)
* [Example](#example)
<!--- END -->
## Overview
- Screenshot tests are tests which record the content of a rendered screen and verify subsequent runs to check if the screen renders differently.
- Element uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify android layouts.
- The screenshot verification occurs on every pull request as part of the `tests.yml` workflow.
## Setup
- Install Git LFS through your package manager of choice (`brew install git-lfs` | `yay -S git-lfs`).
- Install the Git LFS hooks into the project.
```bash
# with element-android as the current working directory
git lfs install --local
```
- If installed correctly, `git push` and `git pull` will now include LFS content.
## Recording
- `./gradlew recordScreenshots`
- Paparazzi will generate images in `${module}/src/test/snapshots`, which will need to be committed to the repository using Git LFS.
## Verifying
- `./gradlew verifyScreenshots`
- In the case of failure, Paparazzi will generate images in `${module}/out/failure`. The images will show the expected and actual screenshots along with a delta of the two images.
## Contributing
- When creating a test, the file (and class) name names must include `ScreenshotTest`, eg `ItemScreenshotTest`.
- After creating the new test, record and commit the newly rendered screens.
- `./tools/validate_lfs` can be ran to ensure everything is working correctly with Git LFS, the CI also runs this check.
## Example
```kotlin
class PaparazziExampleScreenshotTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = PIXEL_3,
theme = "Theme.Vector.Light",
)
@Test
fun `example paparazzi test`() {
// Inflate the layout
val view = paparazzi.inflate<ConstraintLayout>(R.layout.item_radio)
// Bind data to the view
view.findViewById<TextView>(R.id.actionTitle).text = paparazzi.resources.getString(R.string.room_settings_all_messages)
view.findViewById<ImageView>(R.id.radioIcon).setImageResource(R.drawable.ic_radio_on)
// Record the bound view
paparazzi.snapshot(view)
}
}
```

View file

@ -18,7 +18,7 @@ The recently started UnifiedPush project is an Android protocol and library for
The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application. The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application.
The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. A [FCM Rewrite Proxy](https://unifiedpush.org/developers/embedded_fcm/#fcm-rewrite-proxy) is not required for Element Android's implementation of the FCM distributor - it will work with an existing Matrix push provider, such as [Sygnal](https://github.com/matrix-org/sygnal).
The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor. The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor.

351
docs/unit_testing.md Normal file
View file

@ -0,0 +1,351 @@
# Table of Contents
<!--- TOC -->
* [Overview](#overview)
* [Best Practices](#best-practices)
* [Project Conventions](#project-conventions)
* [Setup](#setup)
* [Naming](#naming)
* [Format](#format)
* [Assertions](#assertions)
* [Constants](#constants)
* [Mocking](#mocking)
* [Fakes](#fakes)
* [Fixtures](#fixtures)
* [Examples](#examples)
* [Extensions used to streamline the test setup](#extensions-used-to-streamline-the-test-setup)
* [Fakes and Fixtures](#fakes-and-fixtures)
<!--- END -->
## Overview
Unit tests are a mechanism to validate our code executes the way we expect. They help to inform the design of our systems by requiring testability and
understanding, they describe the inner workings without relying on inline comments and protect from unexpected regressions.
However, unit tests are not a magical solution to solve all our problems and come at a cost. Unreliable and hard to maintain tests often end up ignored, deleted
or worse, provide a false sense of security.
### Best Practices
Tests can be written in many ways, the main rule is to keep them simple and maintainable. Some ways to help achieve this are...
- Break out logic into single units (following the Single Responsibility Principle) to reduce test complexity.
- Favour pure functions, avoiding mutable state.
- Prefer dependency injection to static calls to allow for simpler test setup.
- Write concise tests with a single function under test, clearly showing the inputs and expected output.
- Create separate test cases instead of changing parameters and grouping multiple assertions within a single test to help trace back failure causes (with the
exception of parameterised tests).
- Assert against entire models instead of subsets of properties to capture any possible changes within the test scope.
- Avoid invoking logic from production instances other than the class under test to guard from unrelated changes.
- Always inject `Dispatchers` and `Clock` instances and provide fake implementations for tests to avoid non deterministic results.
## Project Conventions
#### Setup
- Test file and class name should be the class under test with the Test suffix, created in a `test` sourceset, with the same package name as the class under
test.
- Dependencies of the class are instantiated inline, junit will recreate the test class for each test run.
- A line break between the dependencies and class under test helps clarify the instance being tested.
```kotlin
class MyClassTest {
private val fakeUppercaser = FakeUppercaser()
// line break between the class under test and its dependencies
private val myClass = MyClass(fakeUppercaser.instance)
}
```
#### Naming
- Test names use the `Gherkin` format, `given, when, then` mapping to the input, logic under test and expected result.
- `given` - Uniqueness about the environment or dependencies in which the test case is running. _"given device is android 12 and supports dark mode"_
- `when` - The action/function under test. _"when reading dark mode status"_
- `then` - The expected result from the combination of _given_ and _when_. _"then returns dark mode enabled"_
- Test names are written using kotlin back ticks to enable sentences _ish_.
```kotlin
@Test
fun `given a lowercase label, when uppercasing, then returns label uppercased`
```
When the input is given directly to the _when_, this can also be represented as...
```kotlin
@Test
fun `when uppercasing a lowercase label, then returns label uppercased`
```
Multiple given or returns statements can be used in the name although it could be a sign that the logic being tested does too much.
---
#### Format
- Test bodies are broken into sections through the use of blank lines where the sections correspond to the test name.
- Sections can span multiple lines.
```kotlin
// comments are for illustrative purposes
/* given */ val lowercaseLabel = "hello world"
/* when */ val result = textUppercaser.uppercase(lowercaseLabel)
/* then */ result shouldBeEqualTo "HELLO WORLD"
```
- Functions extracted from test bodies are placed beneath all the unit tests.
---
#### Assertions
- Assertions against test results are made using [Kluent's](https://github.com/MarkusAmshove/Kluent) _fluent_ api.
- Typically `shouldBeEqualTo`is the main assertion to use for asserting function return values as by project convention we assert against entire objects or
lists.
```kotlin
val result = listOf("hello", "world")
// Fail
result shouldBeEqualTo listOf("hello")
```
```kotlin
data class Person(val age: Int, val name: String)
val result = Person(age = 100, name = "Gandalf")
// Avoid
result.age shouldBeEqualTo 100
// Prefer
result shouldBeEqualTo Person(age = 100, "Gandalf")
```
- Exception throwing can be asserted against using `assertFailsWith<T : Throwable>`.
- When asserting reusable exceptions, include the message to distinguish between them.
```kotlin
assertFailsWith<ConcreteException>(message = "Details about error") {
// when section of the test
codeUnderTest()
}
```
---
#### Constants
- Reusable values are extracted to file level immutable properties or constants.
- These can be parameters or expected results.
- The naming convention is to prefix with `A` or `AN` for better matching with the test name.
```kotlin
private const val A_LOWERCASE_LABEL = "hello"
class MyTest {
@Test
fun `when uppercasing a lowercase label, then returns label uppercased`() {
val result = TextUppercaser().uppercase(A_LOWERCASE_LABEL)
...
}
}
```
---
#### Mocking
- In order to provide different behaviour for dependencies within tests our main method is through mocking, using [Mockk](https://mockk.io/).
- We avoid using relaxed mocks in favour of explicitly declaring mock behaviour through the _Fake_ convention. There are exceptions when mocking framework
classes which would require a lot of boilerplate.
- Using `Spy` is discouraged as it inherently requires real instances, which we are avoiding in our tests. There are exceptions such as `VectorFeatures` which
acts like a `Fixture` in release builds.
---
#### Fakes
- Fakes are reusable instances of classes purely for testing purposes. They provide functions to replace the functions of the interface/class they're faking
with test specific values.
- When faking an interface, the _Fake_ can be written using delegation or by stubbing
- All Fakes currently reside in the same package `${package}.test.fakes`
```kotlin
// Delegating to a mock
class FakeClock : Clock by mockk() {
fun givenEpoch(epoch: Long) {
every { epochMillis() } returns epoch
}
}
// Stubbing the interface
class FakeClock(private val epoch: Long) : Clock {
override fun epochMillis() = epoch
}
```
It's currently more common for fakes to fake class behaviour, we achieve this by wrapping and exposing a mock instance.
```kotlin
class FakeCursor {
val instance = mockk<Cursor>()
fun givenEmpty() {
every { instance.count } returns 0
every { instance.moveToFirst() } returns false
}
}
val fakeCursor = FakeCursor().apply { givenEmpty() }
```
#### Fixtures
- Fixtures are a reusable wrappers around data models. They provide default values to make creating instances as easy as possible, with the option to override
specific parameters when needed.
- Are namespaced within an `object`.
- Reduces the _find usages_ noise when searching for usages of the origin class construction.
- All Fixtures currently reside in the same package `${package}.test.fixtures`.
```kotlin
object ContentAttachmentDataFixture {
fun aContentAttachmentData(
type: ContentAttachmentData.Type.TEXT,
mimeType: String? = null
) = ContentAttachmentData(type, mimeType)
}
```
- Fixtures can also be used to manage specific combinations of parameters
```kotlin
fun aContentAttachmentAudioData() = aContentAttachmentData(
type = ContentAttachmentData.Type.AUDIO,
mimeType = "audio/mp3",
)
```
---
### Examples
##### Extensions used to streamline the test setup
```kotlin
class CircularCacheTest {
@Test
fun `when putting more than cache size then cache is limited to cache size`() {
val (cache, internalData) = createIntCache(cacheSize = 3)
cache.putInOrder(1, 1, 1, 1, 1, 1)
internalData shouldBeEqualTo arrayOf(1, 1, 1)
}
}
private fun createIntCache(cacheSize: Int): Pair<CircularCache<Int>, Array<Int?>> {
var internalData: Array<Int?>? = null
val factory: (Int) -> Array<Int?> = {
Array<Int?>(it) { null }.also { array -> internalData = array }
}
return CircularCache(cacheSize, factory) to internalData!!
}
private fun CircularCache<Int>.putInOrder(vararg values: Int) {
values.forEach { put(it) }
}
```
##### Fakes and Fixtures
```kotlin
class LateInitUserPropertiesFactoryTest {
private val fakeActiveSessionDataSource = FakeActiveSessionDataSource()
private val fakeVectorStore = FakeVectorStore()
private val fakeContext = FakeContext()
private val fakeSession = FakeSession().also {
it.givenVectorStore(fakeVectorStore.instance)
}
private val lateInitUserProperties = LateInitUserPropertiesFactory(
fakeActiveSessionDataSource.instance,
fakeContext.instance
)
@Test
fun `given no active session, when creating properties, then returns null`() {
val result = lateInitUserProperties.createUserProperties()
result shouldBeEqualTo null
}
@Test
fun `given a teams use case set on an active session, when creating properties, then includes the remapped WorkMessaging selection`() {
fakeVectorStore.givenUseCase(FtueUseCase.TEAMS)
fakeActiveSessionDataSource.setActiveSession(fakeSession)
val result = lateInitUserProperties.createUserProperties()
result shouldBeEqualTo UserProperties(
ftueUseCaseSelection = UserProperties.FtueUseCaseSelection.WorkMessaging
)
}
}
```
##### ViewModel
- `ViewModels` tend to be one of the most complex areas to unit test due to their position as a coordinator of data flows and bridge between domains.
- As the project uses a slightly tweaked`MvRx`, our API for the `ViewModel` is simplified down to `input - ViewModel.handle(Action)`
and `output Flows - ViewModel.viewEvents & ViewModel.stateFlow`. A `ViewModel` test asserter has been created to further simplify the process.
```kotlin
class ViewModelTest {
private var initialState = ViewState.Empty
@get:Rule
val mavericksTestRule = MavericksTestRule(testDispatcher = UnconfinedTestDispatcher())
@Test
fun `when handling MyAction, then emits Loading and Content states`() {
val viewModel = ViewModel<State>(initialState)
val test = viewModel.test() // must be invoked before interacting with the VM
viewModel.handle(MyAction)
test
.assertViewStates(initialState, State.Loading, State.Content())
.assertNoEvents()
.finish()
}
}
```
- `ViewModels` often emit multiple states which are copies of the previous state, the `test` extension `assertStatesChanges` allows only the difference to be
supplied.
```kotlin
data class ViewState(val name: String? = null, val age: Int? = null)
val initialState = ViewState()
val viewModel = ViewModel<State>(initialState)
val test = viewModel.test()
viewModel.handle(ChangeNameAction("Gandalf"))
test
.assertStatesChanges(
initialState,
{ copy(name = "Gandalf") },
)
.finish()
```

View file

@ -0,0 +1 @@
Qrup mesajlaşma - şifrəli mesajlaşma, qrup söhbəti və video zənglər

View file

@ -0,0 +1 @@
Element - Təhlükəsiz Mesajlaşma

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,3 @@
Nový vzhled aplikace lze povolit v Experimentálních funkcích. Prosíme, vyzkoušejte ho!
Oprava problémů s chybějícími oznámeními a dlouhou přírůstkovou synchronizací.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Odložené přímé zprávy jsou ve výchozím nastavení povoleny.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Nové rozvržení aplikace je povoleno ve výchozím nastavení!
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Nové funkce v Experimentálních funkcích: Rozšířený editor zpráv, nová správa zařízení, hlasové vysílání. Stále v aktivním vývoji!
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: nové uživatelské rozhraní pro výběr přílohy.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: nové uživatelské rozhraní pro výběr přílohy.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: opravy různých chyb a vylepšení.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Nová implementace celoobrazovkového režimu pro editor formátovaného textu a opravy chyb.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Nová implementace celoobrazovkového režimu pro editor formátovaného textu a opravy chyb.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Vlákna jsou nyní ve výchozím nastavení povolena.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Vlákna jsou nyní povolena ve výchozím nastavení.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Vlákna jsou nyní povolena ve výchozím nastavení.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: UnifiedPush wird unterstützt; Dies ermöglicht Push-Benachrichtigungen ohne FCM.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verbessertes Anmelde- und Registrierungserlebnis.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verbessertes Anmelde- und Registrierungserlebnis.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,3 @@
Das neue App-Layout kann in den experimentellen Einstellungen aktiviert werden. Probier es gerne aus!
Fehler bzgl. ausbleibender Benachrichtigungen und langwierigem inkrementellem Synchronisieren behoben.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigste Änderung in dieser Version: Verzögerte Direktnachrichten standardmäßig aktiviert!
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigste Änderung in dieser Version: Neues App-Layout standardmäßig aktiviert!
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigste Änderung in dieser Version: Neue Funktionen in den Labor-Einstellungen: Textverarbeitungs-Editor, neue Geräteverwaltung, Sprachübertragung. Noch in aktiver Entwicklung!
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigste Änderung in dieser Version: Neues Anhangauswahl-UI.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigste Änderung in dieser Version: Neue Anhangauswahl-Oberfläche.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Fehlerbehebungen und Verbesserungen.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Der Vollbildmodus des Textverarbeitungseditors wurde neu umgesetzt und es wurden diverse Fehler behoben.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Der Vollbildmodus des Textverarbeitungseditors wurde neu umgesetzt und es wurden diverse Fehler behoben.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Threads sind nun automatisch aktiviert.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Threads sind nun automatisch aktiviert.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Threads sind nun standardmäßig aktiviert.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -1 +1 @@
Gruppen-Messenger - verschlüsselte Kommunikation, Gruppenchat und Videoanrufe Gruppen-Messenger verschlüsselte Kommunikation, Gruppen und Videoanrufe

View file

@ -1 +1 @@
Element - Sicherer Messenger Element Sicher kommunizieren

View file

@ -0,0 +1,2 @@
Main changes in this version: Various bug fixes and stability improvements.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,3 @@
New App Layout can be enabled in the Labs settings. Please give it a try!
Fix issues about missing notification, and long incremental sync.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Deferred DM enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: New app layout enabled by default!
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: New features under the labs settings: Rich text composer, new device management, voice broadcast. Still under active development!
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: new UI for selecting an attachment.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: new UI for selecting an attachment.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: bug fixes and improvements.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: New implementation of the full screen mode for the Rich Text Editor and bugfixes.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: New implementation of the full screen mode for the Rich Text Editor and bugfixes.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Thread are now enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: senisest parem liitumise ja sisselogimise töövoog.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

Some files were not shown because too many files have changed in this diff Show more