diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7d602f0191..e11aa1db91 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,10 +8,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
debug:
@@ -37,7 +35,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble ${{ matrix.target }} debug apk
- run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES
- name: Upload ${{ matrix.target }} debug APKs
uses: actions/upload-artifact@v3
with:
@@ -69,7 +67,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble ${{ matrix.target }} unsigned apk
- run: ./gradlew clean assemble${{ matrix.target }}Release $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ run: ./gradlew clean assemble${{ matrix.target }}Release $CI_GRADLE_ARG_PROPERTIES
- name: Upload ${{ matrix.target }} unsigned APKs
uses: actions/upload-artifact@v3
with:
diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml
new file mode 100644
index 0000000000..a1d754b4de
--- /dev/null
+++ b/.github/workflows/danger.yml
@@ -0,0 +1,18 @@
+name: Danger CI
+
+on: [pull_request]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ name: Danger
+ steps:
+ - uses: actions/checkout@v3
+ - run: |
+ npm install --save-dev @babel/plugin-transform-flow-strip-types
+ - name: Danger
+ uses: danger/danger-js@11.1.1
+ with:
+ args: "--dangerfile tools/danger/dangerfile.js"
+ env:
+ DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml
index 4e701faa44..7b68c0077d 100644
--- a/.github/workflows/gradle-wrapper-validation.yml
+++ b/.github/workflows/gradle-wrapper-validation.yml
@@ -1,5 +1,8 @@
name: "Validate Gradle Wrapper"
-on: [push, pull_request]
+on:
+ pull_request: { }
+ push:
+ branches: [ main, develop ]
jobs:
validation:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 49934b7fa4..6232176f49 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -6,10 +6,8 @@ on:
- cron: "0 4 * * *"
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
nightly:
@@ -42,7 +40,7 @@ jobs:
yes n | towncrier build --version nightly
- name: Build and upload Gplay Nightly APK
run: |
- ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES
env:
ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }}
ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }}
diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml
index add707e7d9..ced52e087a 100644
--- a/.github/workflows/post-pr.yml
+++ b/.github/workflows/post-pr.yml
@@ -10,10 +10,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 34910763e3..6e5e2e4d67 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -1,4 +1,3 @@
-
name: Code Quality Checks
on:
@@ -8,10 +7,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
check:
@@ -30,79 +27,50 @@ jobs:
- uses: actions/checkout@v3
- name: Run knit
run: |
- ./gradlew knit
+ ./gradlew knitCheck
- # ktlint for all the modules
- ktlint:
- name: Kotlin Linter
+ # Check the project: ktlint, detekt, lint
+ lint:
+ name: Android Linter
runs-on: ubuntu-latest
# Allow all jobs on main and develop. Just one per PR.
concurrency:
- group: ${{ github.ref == 'refs/heads/main' && format('ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('ktlint-develop-{0}', github.sha) || format('ktlint-{0}', github.ref) }}
+ group: ${{ github.ref == 'refs/heads/main' && format('lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('lint-develop-{0}', github.sha) || format('lint-{0}', github.ref) }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v3
- name: Run ktlint
run: |
./gradlew ktlintCheck --continue
+ - name: Run detekt
+ if: always()
+ run: |
+ ./gradlew detekt $CI_GRADLE_ARG_PROPERTIES
+ - name: Run lint
+ # Not always, if ktlint or detekt fail, avoid running the long lint check.
+ run: |
+ ./gradlew lintGplayRelease $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew lintFdroidRelease $CI_GRADLE_ARG_PROPERTIES
- name: Upload reports
if: always()
uses: actions/upload-artifact@v3
with:
- name: ktlinting-report
+ name: linting-report
path: |
- */build/reports/ktlint/ktlint*/ktlint*.txt
- - name: Handle Results
+ */build/reports/**/*.*
+ - name: Prepare Danger
if: always()
- id: ktlint-results
run: |
- results="$(cat */*/build/reports/ktlint/ktlint*/ktlint*.txt */build/reports/ktlint/ktlint*/ktlint*.txt | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g")"
- if [ -z "$results" ]; then
- echo "::set-output name=add_comment::false"
- else
- body="👎\`Failed${results}\`"
- body="${body//'%'/'%25'}"
- body="${body//$'\n'/'%0A'}"
- body="${body//$'\r'/'%0D'}"
- body="$( echo $body | sed 's/\/home\/runner\/work\/tchap-android\/tchap-android\//\`
\`/g')"
- body="$( echo $body | sed 's/\/src\/main\/java\// 🔸 /g')"
- body="$( echo $body | sed 's/im\/vector\/app\///g')"
- body="$( echo $body | sed 's/im\/vector\/lib\/attachmentviewer\///g')"
- body="$( echo $body | sed 's/im\/vector\/lib\/multipicker\///g')"
- body="$( echo $body | sed 's/im\/vector\/lib\///g')"
- body="$( echo $body | sed 's/org\/matrix\/android\/sdk\///g')"
- body="$( echo $body | sed 's/\/src\/androidTest\/java\// 🔸 /g')"
- echo "::set-output name=add_comment::true"
- echo "::set-output name=body::$body"
- fi
- - name: Find Comment
- if: always() && github.event_name == 'pull_request'
- uses: peter-evans/find-comment@v2
- id: fc
- with:
- issue-number: ${{ github.event.pull_request.number }}
- comment-author: 'github-actions[bot]'
- body-includes: Ktlint Results
- - name: Add comment if needed
- if: always() && github.event_name == 'pull_request' && steps.ktlint-results.outputs.add_comment == 'true'
- uses: peter-evans/create-or-update-comment@v2
- with:
- comment-id: ${{ steps.fc.outputs.comment-id }}
- issue-number: ${{ github.event.pull_request.number }}
- body: |
- ### Ktlint Results
- ${{ steps.ktlint-results.outputs.body }}
- edit-mode: replace
- - name: Delete comment if needed
- if: always() && github.event_name == 'pull_request' && steps.fc.outputs.comment-id != '' && steps.ktlint-results.outputs.add_comment == 'false'
- uses: actions/github-script@v3
+ npm install --save-dev @babel/core
+ npm install --save-dev @babel/plugin-transform-flow-strip-types
+ yarn add danger-plugin-lint-report --dev
+ - name: Danger lint
+ if: always()
+ uses: danger/danger-js@11.1.1
with:
- script: |
- github.issues.deleteComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- comment_id: ${{ steps.fc.outputs.comment-id }}
- })
+ args: "--dangerfile tools/danger/dangerfile-lint.js"
+ env:
+ DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
dependency-analysis:
@@ -122,107 +90,3 @@ jobs:
with:
name: dependency-analysis
path: build/reports/dependency-check-report.html
-
- # Lint for main module
- android-lint:
- name: Android Linter
- runs-on: ubuntu-latest
- # Allow all jobs on main and develop. Just one per PR.
- concurrency:
- group: ${{ github.ref == 'refs/heads/main' && format('android-lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('android-lint-develop-{0}', github.sha) || format('android-lint-{0}', github.ref) }}
- cancel-in-progress: true
- steps:
- - uses: actions/checkout@v3
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - name: Lint analysis
- run: ./gradlew clean :vector:lint --stacktrace $CI_GRADLE_ARG_PROPERTIES
- - name: Upload reports
- if: always()
- uses: actions/upload-artifact@v3
- with:
- name: lint-report
- path: |
- vector/build/reports/*.*
-
- # Lint for Gplay and Fdroid release APK
- apk-lint:
- name: Lint APK (${{ matrix.target }})
- runs-on: ubuntu-latest
- if: github.ref != 'refs/heads/main'
- strategy:
- fail-fast: false
- matrix:
- target: [ GplayBtchapWithoutvoipWithpinning, FdroidBtchapWithoutvoipWithoutpinning ]
- # Allow all jobs on develop. Just one per PR.
- concurrency:
- group: ${{ github.ref == 'refs/heads/develop' && format('apk-lint-develop-{0}-{1}', matrix.target, github.sha) || format('apk-lint-{0}-{1}', matrix.target, github.ref) }}
- cancel-in-progress: true
- steps:
- - uses: actions/checkout@v3
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - name: Lint ${{ matrix.target }} release
- run: ./gradlew clean lint${{ matrix.target }}Release --stacktrace $CI_GRADLE_ARG_PROPERTIES
- - name: Upload ${{ matrix.target }} linting report
- if: always()
- uses: actions/upload-artifact@v3
- with:
- name: release-lint-report-${{ matrix.target }}
- path: |
- vector/build/reports/*.*
-
- detekt:
- name: Detekt Analysis
- runs-on: ubuntu-latest
- # Allow all jobs on main and develop. Just one per PR.
- concurrency:
- group: ${{ github.ref == 'refs/heads/main' && format('detekt-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('detekt-develop-{0}', github.sha) || format('detekt-{0}', github.ref) }}
- cancel-in-progress: true
- steps:
- - uses: actions/checkout@v3
- - name: Run detekt
- run: |
- ./gradlew detekt $CI_GRADLE_ARG_PROPERTIES
- - name: Upload reports
- if: always()
- uses: actions/upload-artifact@v3
- with:
- name: detekt-report
- path: |
- */build/reports/detekt/detekt.html
-
-# towncrier:
-# name: Towncrier check
-# runs-on: ubuntu-latest
-# if: github.event_name == 'pull_request' && github.head_ref == 'develop'
-# steps:
-# - uses: actions/checkout@v3
-# - name: Set up Python 3.8
-# uses: actions/setup-python@v4
-# with:
-# python-version: 3.8
-# - name: Install towncrier
-# run: |
-# python3 -m pip install towncrier
-# - name: Run towncrier
-# # Fetch the pull request' base branch so towncrier will be able to
-# # compare the current branch with the base branch.
-# # Source: https://github.com/actions/checkout/#fetch-all-branches.
-# run: |
-# git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH}
-# towncrier check --compare-with origin/${BASE_BRANCH}
-# env:
-# BASE_BRANCH: ${{ github.base_ref }}
diff --git a/.github/workflows/sanity_test.yml b/.github/workflows/sanity_test.yml
index 3d411d3965..911ab62b1c 100644
--- a/.github/workflows/sanity_test.yml
+++ b/.github/workflows/sanity_test.yml
@@ -70,7 +70,7 @@ jobs:
touch emulator.log
chmod 777 emulator.log
adb logcat >> emulator.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedGplayBtchapWithoutvoipWithpinningDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || adb pull storage/emulated/0/Pictures/failure_screenshots && exit 1
+ ./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedGplayBtchapWithoutvoipWithoutpinningDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || adb pull storage/emulated/0/Pictures/failure_screenshots && exit 1
- name: Upload Test Report Log
uses: actions/upload-artifact@v2
if: always()
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 30bd283a12..952f6c7d51 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,10 +7,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
tests:
@@ -51,9 +49,9 @@ jobs:
disable-animations: true
emulator-build: 7425822
script: |
- ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./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
@@ -67,16 +65,16 @@ jobs:
disable-animations: true
emulator-build: 7425822
script: |
- ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
- # Tchap: Skip for forks
-# - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
-# if: always() # we may have failed a previous step and retried, that's OK
-# env:
-# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
-# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
-# ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
+ ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
+ - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
+ # Tchap: Skip in forks
+ if: github.repository == 'vector-im/element-android' && always() # we may have failed a previous step and retried, that's OK
+ env:
+ GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
- name: Format unit test results
if: always()
@@ -115,4 +113,4 @@ jobs:
# restore-keys: |
# ${{ runner.os }}-gradle-
# - name: Build Android Tests
-# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
+# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES
diff --git a/.gitignore b/.gitignore
index 8313fb5c63..f1c0b99b58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,8 @@
/fastlane/report.xml
/**/build
+
+# Added by yarn
+/package.json
+/yarn.lock
+/node_modules
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6e67639284..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-# FTR: Configuration on https://travis-ci.org/github/vector-im/element-android/settings
-#
-# - Build only if .travis.yml is present -> On
-# - Limit concurrent jobs -> Off
-# - Build pushed branches -> On (build the branch)
-# - Build pushed pull request -> On (build the PR after auto-merge)
-#
-# - Auto cancel branch builds -> On
-# - Auto cancel pull request builds -> On
-
-sudo: false
-
-notifications:
- email: false
-
-# Just run a simple script here
-script:
- - ./tools/travis/check_pr.sh
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 44b87c6141..108fa46424 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -103,7 +103,7 @@ For ktlint to fix some detected errors for you (you still have to check and comm
Make sure the following commands execute without any error:
-./gradlew testGplayBtchapWithoutvoipWithpinningReleaseUnitTest
+./gradlew testGplayBtchapWithoutvoipWithoutpinningReleaseUnitTest
### Tests
diff --git a/ELEMENT_CHANGES.md b/ELEMENT_CHANGES.md
index 2c6fc1501c..829b1a0caa 100644
--- a/ELEMENT_CHANGES.md
+++ b/ELEMENT_CHANGES.md
@@ -1,3 +1,47 @@
+Changes in Element v1.4.32 (2022-08-10)
+=======================================
+
+Features ✨
+----------
+ - [Location Share] Render fallback UI when map fails to load ([#6711](https://github.com/vector-im/element-android/issues/6711))
+
+Bugfixes 🐛
+----------
+ - Fix message content sometimes appearing in the log ([#6706](https://github.com/vector-im/element-android/issues/6706))
+ - Disable 'Enable biometrics' option if there are not biometric authenticators enrolled. ([#6713](https://github.com/vector-im/element-android/issues/6713))
+ - Fix crash when biometric key is used when coming back to foreground and KeyStore reports that the device is still locked. ([#6768](https://github.com/vector-im/element-android/issues/6768))
+ - Catch all exceptions on lockscreen system key migrations. ([#6769](https://github.com/vector-im/element-android/issues/6769))
+ - Fixes crash when entering non ascii characters during account creation ([#6735](https://github.com/vector-im/element-android/issues/6735))
+ - Fixes onboarding login/account creation errors showing after navigation ([#6737](https://github.com/vector-im/element-android/issues/6737))
+ - [Location sharing] Invisible text on map symbol ([#6687](https://github.com/vector-im/element-android/issues/6687))
+
+In development 🚧
+----------------
+ - Adds new app layout toolbar ([#6655](https://github.com/vector-im/element-android/issues/6655))
+
+Other changes
+-------------
+ - [Modularization] Provides abstraction to avoid direct usages of BuildConfig ([#6406](https://github.com/vector-im/element-android/issues/6406))
+ - Refactors SpaceStateHandler (previously AppStateHandler) and adds unit tests for it ([#6598](https://github.com/vector-im/element-android/issues/6598))
+ - Setup Danger to the project ([#6637](https://github.com/vector-im/element-android/issues/6637))
+ - [Location Share] Open maximized map on tapping on live sharing notification ([#6642](https://github.com/vector-im/element-android/issues/6642))
+ - [Location sharing] Align naming of components for live location feature ([#6647](https://github.com/vector-im/element-android/issues/6647))
+ - [Location share] Update minimum sending period to 5 seconds for a live ([#6653](https://github.com/vector-im/element-android/issues/6653))
+ - [Location sharing] - Fix the memory leaks ([#6674](https://github.com/vector-im/element-android/issues/6674))
+ - [Timeline] Memory leak in audio message playback tracker ([#6678](https://github.com/vector-im/element-android/issues/6678))
+ - [FTUE] Memory leak on FtueAuthSplashCarouselFragment ([#6680](https://github.com/vector-im/element-android/issues/6680))
+ - Link directly to DCO docs from danger message. ([#6739](https://github.com/vector-im/element-android/issues/6739))
+
+
+Changes in Element v1.4.31 (2022-08-01)
+=======================================
+
+Bugfixes 🐛
+----------
+ - Fixes crash when returning to the app after backgrounding ([#6709](https://github.com/vector-im/element-android/issues/6709))
+ - Fix message content sometimes appearing in the log ([#6706](https://github.com/vector-im/element-android/issues/6706))
+
+
Changes in Element v1.4.30 (2022-07-29)
=======================================
diff --git a/Gemfile b/Gemfile
index 7a118b49be..c90138ee44 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,4 @@
source "https://rubygems.org"
gem "fastlane"
+gem 'danger'
diff --git a/Gemfile.lock b/Gemfile.lock
index 345b4c1502..90e846860e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -24,10 +24,29 @@ GEM
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
+ claide-plugins (0.9.2)
+ cork
+ nap
+ open4 (~> 1.3)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
+ cork (0.3.0)
+ colored2 (~> 3.1)
+ danger (8.6.1)
+ claide (~> 1.0)
+ claide-plugins (>= 0.9.2)
+ colored2 (~> 3.1)
+ cork (~> 0.1)
+ faraday (>= 0.9.0, < 2.0)
+ faraday-http-cache (~> 2.0)
+ git (~> 1.7)
+ kramdown (~> 2.3)
+ kramdown-parser-gfm (~> 1.0)
+ no_proxy_fix
+ octokit (~> 4.7)
+ terminal-table (>= 1, < 4)
declarative (0.0.20)
digest-crc (0.6.3)
rake (>= 12.0.0, < 14.0.0)
@@ -52,6 +71,8 @@ GEM
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
+ faraday-http-cache (2.4.0)
+ faraday (>= 0.8)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
@@ -98,6 +119,8 @@ GEM
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
+ git (1.11.0)
+ rchardet (~> 1.8)
google-apis-androidpublisher_v3 (0.8.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.4.0)
@@ -143,17 +166,28 @@ GEM
jmespath (1.4.0)
json (2.5.1)
jwt (2.2.3)
+ kramdown (2.4.0)
+ rexml
+ kramdown-parser-gfm (1.1.0)
+ kramdown (~> 2.0)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.0)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
+ nap (1.1.0)
naturally (2.2.1)
+ no_proxy_fix (0.1.2)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
+ open4 (1.3.4)
os (1.1.1)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.6)
+ rchardet (1.8.0)
representable (3.1.1)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
@@ -163,6 +197,9 @@ GEM
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
+ sawyer (0.9.2)
+ addressable (>= 2.3.5)
+ faraday (>= 0.17.3, < 3)
security (0.1.3)
signet (0.15.0)
addressable (~> 2.3)
@@ -200,9 +237,11 @@ GEM
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
+ universal-darwin-21
x86_64-darwin-20
DEPENDENCIES
+ danger
fastlane
BUNDLED WITH
diff --git a/build.gradle b/build.gradle
index 33c6edd599..13ae745dbb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,7 +30,7 @@ buildscript {
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
classpath "com.likethesalad.android:stem-plugin:2.1.1"
classpath 'org.owasp:dependency-check-gradle:7.1.1'
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.0"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -41,10 +41,10 @@ plugins {
// ktlint Plugin
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
// Detekt
- id "io.gitlab.arturbosch.detekt" version "1.20.0"
+ id "io.gitlab.arturbosch.detekt" version "1.21.0"
// Dependency Analysis
- id 'com.autonomousapps.dependency-analysis' version "1.9.0"
+ id 'com.autonomousapps.dependency-analysis' version "1.11.2"
}
// https://github.com/jeremylong/DependencyCheck
@@ -126,6 +126,11 @@ allprojects {
enableExperimentalRules = true
// display the corresponding rule
verbose = true
+ reporters {
+ reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.PLAIN)
+ // To have XML report for Danger
+ reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
+ }
disabledRules = [
// TODO Re-enable these 4 rules after reformatting project
"indent",
diff --git a/coverage.gradle b/coverage.gradle
index 2f349b77bc..76b70a4476 100644
--- a/coverage.gradle
+++ b/coverage.gradle
@@ -81,11 +81,11 @@ task generateCoverageReport(type: JacocoReport) {
task unitTestsWithCoverage(type: GradleBuild) {
// the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage
startParameter.projectProperties.coverage = [enableTestCoverage: false]
- tasks = [':vector:testGplayBtchapWithoutvoipWithpinningDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest']
+ tasks = [':vector:testGplayBtchapWithoutvoipWithoutpinningDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest']
}
task instrumentationTestsWithCoverage(type: GradleBuild) {
startParameter.projectProperties.coverage = [enableTestCoverage: true]
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
- tasks = [':vector:connectedGplayBtchapWithoutvoipWithpinningDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest']
+ tasks = [':vector:connectedGplayBtchapWithoutvoipWithoutpinningDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest']
}
diff --git a/dependencies.gradle b/dependencies.gradle
index e8e39dc5f7..93a62a548e 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -20,9 +20,9 @@ def retrofit = "2.9.0"
def arrow = "0.8.2"
def markwon = "4.6.2"
def moshi = "1.13.0"
-def lifecycle = "2.5.0"
+def lifecycle = "2.5.1"
def flowBinding = "1.2.0"
-def flipper = "0.154.0"
+def flipper = "0.156.0"
def epoxy = "4.6.2"
def mavericks = "2.7.0"
def glide = "4.13.2"
@@ -30,7 +30,7 @@ def bigImageViewer = "1.8.1"
def jjwt = "0.11.5"
def vanniktechEmoji = "0.15.0"
-def fragment = "1.5.0"
+def fragment = "1.5.1"
// 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
@@ -50,7 +50,7 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
- 'activity' : "androidx.activity:activity:1.5.0",
+ 'activity' : "androidx.activity:activity:1.5.1",
'appCompat' : "androidx.appcompat:appcompat:1.4.2",
'biometric' : "androidx.biometric:biometric:1.1.0",
'core' : "androidx.core:core-ktx:1.8.0",
diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle
index e89c69a594..d5972ed846 100644
--- a/dependencies_groups.gradle
+++ b/dependencies_groups.gradle
@@ -74,6 +74,7 @@ ext.groups = [
'com.github.javaparser',
'com.github.piasy',
'com.github.shyiko.klob',
+ 'com.github.rubensousa',
'com.google',
'com.google.android',
'com.google.api.grpc',
@@ -125,6 +126,7 @@ ext.groups = [
'info.picocli',
'io.arrow-kt',
'io.element.android',
+ 'io.github.davidburstrom.contester',
'io.github.detekt.sarif4k',
'io.github.microutils',
'io.github.reactivecircus.flowbinding',
diff --git a/docs/danger.md b/docs/danger.md
new file mode 100644
index 0000000000..19728f00e9
--- /dev/null
+++ b/docs/danger.md
@@ -0,0 +1,102 @@
+## Danger
+
+
+
+* [What does danger checks](#what-does-danger-checks)
+ * [PR check](#pr-check)
+ * [Quality check](#quality-check)
+* [Setup](#setup)
+* [Run danger locally](#run-danger-locally)
+* [Danger user](#danger-user)
+* [Useful links](#useful-links)
+
+
+
+## What does danger checks
+
+### PR check
+
+See the [dangerfile](../tools/danger/dangerfile.js). If you add rules in the dangerfile, please update the list below!
+
+Here are the checks that Danger does so far:
+
+- PR description is not empty
+- Big PR got a warning to recommend to split
+- PR contains a file for towncrier and extension is checked
+- PR contains a Sign-Off, with exception for Element employee contributors
+- PR with change on layout should include screenshot in the description
+- PR which adds png file warn about the usage of vector drawables
+- non draft PR should have a reviewer
+
+### Quality check
+
+After all the checks that generate checkstyle XML report, such as Ktlint, lint, or Detekt, Danger is run with this [dangerfile](../tools/danger/dangerfile-lint.js), in order to post comments to the PR with the detected error and warnings.
+
+To run locally, you will have to install the plugin `danger-plugin-lint-report` using:
+
+```shell
+yarn add danger-plugin-lint-report --dev
+```
+
+## Setup
+
+This operation should not be necessary, since Danger is already setup for the project.
+
+To setup danger to the project, run:
+
+```shell
+bundle exec danger init
+```
+
+## Run danger locally
+
+When modifying the [dangerfile](../tools/danger/dangerfile.js), you can check it by running Danger locally.
+
+To run danger locally, install it and run:
+
+```shell
+bundle exec danger pr --dangerfile=./tools/danger/dangerfile.js
+```
+
+For instance:
+
+```shell
+bundle exec danger pr https://github.com/vector-im/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
+```
+
+We may need to create a GitHub token to have less API rate limiting, and then set the env var:
+
+```shell
+export DANGER_GITHUB_API_TOKEN='YOUR_TOKEN'
+```
+
+Swift and Kotlin (just in case)
+
+```shell
+bundle exec danger-swift pr --dangerfile=./tools/danger/dangerfile.js
+bundle exec danger-kotlin pr --dangerfile=./tools/danger/dangerfile.js
+```
+
+## Danger user
+
+To let Danger check all the PRs, including PRs form forks, a GitHub account have been created:
+- login: ElementBot
+- password: Stored on Passbolt
+- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
+
+## Useful links
+
+- https://danger.systems/
+- https://danger.systems/js/
+- https://danger.systems/js/guides/getting_started.html
+- https://danger.systems/js/reference.html
+- https://github.com/danger/awesome-danger
+
+Some danger files to get inspired from
+
+- https://github.com/artsy/emission/blob/master/dangerfile.ts
+- https://github.com/facebook/react-native/blob/master/bots/dangerfile.js
+- https://github.com/apollographql/apollo-client/blob/master/config/dangerfile.ts
+- https://github.com/styleguidist/react-styleguidist/blob/master/dangerfile.js
+- https://github.com/storybooks/storybook/blob/master/dangerfile.js
+- https://github.com/ReactiveX/rxjs/blob/master/dangerfile.js
diff --git a/docs/nightly_build.md b/docs/nightly_build.md
index 91f18214c4..7750e0466a 100644
--- a/docs/nightly_build.md
+++ b/docs/nightly_build.md
@@ -48,7 +48,7 @@ mv towncrier.toml towncrier.toml.bak
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
rm towncrier.toml.bak
yes n | towncrier --version nightly
-./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace
+./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES
```
Then you can reset the change on the codebase.
diff --git a/fastlane/metadata/android/en-US/changelogs/40104310.txt b/fastlane/metadata/android/en-US/changelogs/40104310.txt
new file mode 100644
index 0000000000..c0b3284c4f
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104310.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Enables the improved sign in and sign up journeys.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104320.txt b/fastlane/metadata/android/en-US/changelogs/40104320.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104320.txt
@@ -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
diff --git a/library/ui-styles/src/main/res/drawable/ic_home_search.xml b/library/ui-styles/src/main/res/drawable/ic_home_search.xml
new file mode 100644
index 0000000000..5cb88ba1e4
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/ic_home_search.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 70d051b457..53f1044a12 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -71,4 +71,7 @@
8dp
12dp
22dp
+
+
+ 112dp
diff --git a/library/ui-styles/src/main/res/values/stylable_location_live_ended_banner_view.xml b/library/ui-styles/src/main/res/values/stylable_live_location_ended_banner_view.xml
similarity index 79%
rename from library/ui-styles/src/main/res/values/stylable_location_live_ended_banner_view.xml
rename to library/ui-styles/src/main/res/values/stylable_live_location_ended_banner_view.xml
index 81e377d39b..30ac6229c5 100644
--- a/library/ui-styles/src/main/res/values/stylable_location_live_ended_banner_view.xml
+++ b/library/ui-styles/src/main/res/values/stylable_live_location_ended_banner_view.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml b/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml
new file mode 100644
index 0000000000..911167e52a
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/values/styles_location.xml b/library/ui-styles/src/main/res/values/styles_location.xml
index 41ddbc73ca..ee893046ba 100644
--- a/library/ui-styles/src/main/res/values/styles_location.xml
+++ b/library/ui-styles/src/main/res/values/styles_location.xml
@@ -1,7 +1,7 @@
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/values/text_appearances.xml b/library/ui-styles/src/main/res/values/text_appearances.xml
index 1e60e05acf..570d26fdfd 100644
--- a/library/ui-styles/src/main/res/values/text_appearances.xml
+++ b/library/ui-styles/src/main/res/values/text_appearances.xml
@@ -32,6 +32,15 @@
- ?vctr_content_primary
+
+
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml
index b88feb40f2..2f65b77c69 100644
--- a/library/ui-styles/src/main/res/values/theme_dark.xml
+++ b/library/ui-styles/src/main/res/values/theme_dark.xml
@@ -150,6 +150,9 @@
- @color/vctr_live_location_dark
+
+
+ - @dimen/collapsing_toolbar_layout_medium_size
diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml
index 4d3490f7de..1f83eb57a7 100644
--- a/library/ui-styles/src/main/res/values/theme_light.xml
+++ b/library/ui-styles/src/main/res/values/theme_light.xml
@@ -151,8 +151,12 @@
- @color/vctr_live_location_light
+
+
+ - @dimen/collapsing_toolbar_layout_medium_size
+
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index ee58db748c..45a962f12c 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -60,7 +60,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
- buildConfigField "String", "SDK_VERSION", "\"1.4.30\""
+ buildConfigField "String", "SDK_VERSION", "\"1.4.32\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@@ -199,7 +199,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
index a78953caac..f30d2dab81 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
@@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
@@ -103,7 +104,9 @@ class CommonTestHelper internal constructor(context: Context) {
context,
MatrixConfiguration(
applicationFlavor = "TestFlavor",
- roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
+ roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider(),
+ // Tchap: Do not limit here key requests to my devices to unblock crypto tests
+ cryptoConfig = MXCryptoConfig(limitRoomKeyRequestsToMyDevices = false),
)
)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
index 6e198fb98c..68b931b33c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
@@ -62,7 +62,10 @@ fun Throwable.isUsernameInUse() = this is Failure.ServerError &&
error.code == MatrixError.M_USER_IN_USE
fun Throwable.isInvalidUsername() = this is Failure.ServerError &&
- error.code == MatrixError.M_INVALID_USERNAME
+ (error.code == MatrixError.M_INVALID_USERNAME || usernameContainsNonAsciiCharacters())
+
+private fun Failure.ServerError.usernameContainsNonAsciiCharacters() = error.code == MatrixError.M_UNKNOWN &&
+ error.message == "Query parameter \'username\' must be ascii"
fun Throwable.isInvalidPassword() = this is Failure.ServerError &&
error.code == MatrixError.M_FORBIDDEN &&
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/StringOrderUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/StringOrderUtils.kt
index 83c8585941..1de0a36034 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/StringOrderUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/StringOrderUtils.kt
@@ -76,7 +76,7 @@ object StringOrderUtils {
}
fun stringToBase(x: String, alphabet: CharArray): BigInteger {
- if (x.isEmpty()) throw IllegalArgumentException()
+ require(x.isNotEmpty())
val len = alphabet.size.toBigInteger()
var result = BigInteger("0")
x.reversed().forEachIndexed { index, c ->
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
index 96d97a41d7..771b5f9a62 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
@@ -535,7 +535,7 @@ internal class MXMegolmEncryption(
@Throws
override suspend fun shareHistoryKeysWithDevice(inboundSessionWrapper: InboundGroupSessionHolder, deviceInfo: CryptoDeviceInfo) {
- if (!inboundSessionWrapper.wrapper.sessionData.sharedHistory) throw IllegalArgumentException("This key can't be shared")
+ require(inboundSessionWrapper.wrapper.sessionData.sharedHistory) { "This key can't be shared" }
Timber.tag(loggerTag.value).i("process shareHistoryKeys for ${inboundSessionWrapper.wrapper.safeSessionId} to ${deviceInfo.shortDebugString()}")
val userId = deviceInfo.userId
val deviceId = deviceInfo.deviceId
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt
index 821663bcff..8a805a5588 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt
@@ -63,7 +63,7 @@ internal class VerificationMessageProcessor @Inject constructor(
// the message should be ignored by the receiver.
if (!VerificationService.isValidRequest(event.ageLocalTs, clock.epochMillis())) return Unit.also {
- Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is outdated age:$event.ageLocalTs ms")
+ Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is outdated age:${event.ageLocalTs} ms")
}
Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} type: ${event.getClearType()}")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
index c5b13043d7..51107c9655 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
@@ -119,7 +119,7 @@ internal class EventSenderProcessorThread @Inject constructor(
override fun cancel(eventId: String, roomId: String) {
(currentTask as? SendEventQueuedTask)
- ?.takeIf { it -> it.event.eventId == eventId && it.event.roomId == roomId }
+ ?.takeIf { it.event.eventId == eventId && it.event.roomId == roomId }
?.cancel()
}
diff --git a/tools/danger/dangerfile-lint.js b/tools/danger/dangerfile-lint.js
new file mode 100644
index 0000000000..b0531fef9b
--- /dev/null
+++ b/tools/danger/dangerfile-lint.js
@@ -0,0 +1,29 @@
+import { schedule } from 'danger'
+
+/**
+ * Ref and documentation: https://github.com/damian-burke/danger-plugin-lint-report
+ * This file will check all the error in XML Checkstyle format.
+ * It covers, lint, ktlint, and detekt errors
+ */
+
+const reporter = require("danger-plugin-lint-report")
+schedule(reporter.scan({
+ /**
+ * File mask used to find XML checkstyle reports.
+ */
+ fileMask: "**/reports/**/**.xml",
+ /**
+ * If set to true, the severity will be used to switch between the different message formats (message, warn, fail).
+ */
+ reportSeverity: true,
+ /**
+ * If set to true, only issues will be reported that are contained in the current changeset (line comparison).
+ * If set to false, all issues that are in modified files will be reported.
+ */
+ requireLineModification: false,
+ /**
+ * Optional: Sets a prefix foreach violation message.
+ * This can be useful if there are multiple reports being parsed to make them distinguishable.
+ */
+ // outputPrefix?: ""
+}))
diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js
new file mode 100644
index 0000000000..4efd236419
--- /dev/null
+++ b/tools/danger/dangerfile.js
@@ -0,0 +1,107 @@
+const {danger, warn} = require('danger')
+
+/**
+ * Note: if you update the checks in this file, please also update the file ./docs/danger.md
+ */
+
+// Useful to see what we got in danger object
+// warn(JSON.stringify(danger))
+
+const pr = danger.github.pr
+const github = danger.github
+// User who has created the PR.
+const user = pr.user.login
+const modified = danger.git.modified_files
+const created = danger.git.created_files
+const editedFiles = [...modified, ...created]
+
+// Check that the PR has a description
+if (pr.body.length == 0) {
+ warn("Please provide a description for this PR.")
+}
+
+// Warn when there is a big PR
+if (editedFiles.length > 50) {
+ message("This pull request seems relatively large. Please consider splitting it into multiple smaller ones.")
+}
+
+// Request a changelog for each PR
+const changelogAllowList = [
+ "dependabot[bot]",
+]
+
+const requiresChangelog = !changelogAllowList.includes(user)
+
+if (requiresChangelog) {
+ const changelogFiles = editedFiles.filter(file => file.startsWith("changelog.d/"))
+
+ if (changelogFiles.length == 0) {
+ warn("Please add a changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ } else {
+ const validTowncrierExtensions = [
+ "bugfix",
+ "doc",
+ "feature",
+ "misc",
+ "sdk",
+ "wip",
+ ]
+ if (!changelogFiles.every(file => validTowncrierExtensions.includes(file.split(".").pop()))) {
+ fail("Invalid extension for changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ }
+ }
+}
+
+// Check for a sign-off
+const signOff = "Signed-off-by:"
+
+// Please add new names following the alphabetical order.
+const allowList = [
+ "aringenbach",
+ "BillCarsonFr",
+ "bmarty",
+ "Claire1817",
+ "dependabot[bot]",
+ "ericdecanini",
+ "fedrunov",
+ "Florian14",
+ "ganfra",
+ "jmartinesp",
+ "langleyd",
+ "MadLittleMods",
+ "manuroe",
+ "mnaturel",
+ "onurays",
+ "ouchadam",
+ "stefanceriu",
+ "yostyle",
+]
+
+const requiresSignOff = !allowList.includes(user)
+
+if (requiresSignOff) {
+ const hasPRBodySignOff = pr.body.includes(signOff)
+ const hasCommitSignOff = danger.git.commits.every(commit => commit.message.includes(signOff))
+ if (!hasPRBodySignOff && !hasCommitSignOff) {
+ fail("Please add a sign-off to either the PR description or to the commits themselves. See instructions [here](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off).")
+ }
+}
+
+// Check for screenshots on view changes
+const hasChangedViews = editedFiles.filter(file => file.includes("/layout")).length > 0
+if (hasChangedViews) {
+ if (!pr.body.includes("user-images")) {
+ warn("You seem to have made changes to views. Please consider adding screenshots.")
+ }
+}
+
+// Check for pngs on resources
+const hasPngs = editedFiles.filter(file => file.toLowerCase().endsWith(".png")).length > 0
+if (hasPngs) {
+ warn("You seem to have made changes to some images. Please consider using an vector drawable.")
+}
+
+// Check for reviewers
+if (github.requested_reviewers.users.length == 0 && !pr.draft) {
+ warn("Please add a reviewer to your PR.")
+}
diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml
index a836edc47a..96adb3d117 100644
--- a/tools/detekt/detekt.yml
+++ b/tools/detekt/detekt.yml
@@ -23,6 +23,8 @@ style:
active: false
ProtectedMemberInFinalClass:
active: false
+ UseCheckOrError:
+ active: false
empty-blocks:
EmptyFunctionBlock:
@@ -43,6 +45,8 @@ exceptions:
active: false
TooGenericExceptionThrown:
active: false
+ InstanceOfCheckForException:
+ active: false
complexity:
TooManyFunctions:
diff --git a/tools/travis/check_pr.sh b/tools/travis/check_pr.sh
deleted file mode 100755
index d8d95879e2..0000000000
--- a/tools/travis/check_pr.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-
-#
-# Copyright 2018 New Vector Ltd
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-branch=${TRAVIS_BRANCH}
-
-# echo ${TRAVIS_BRANCH}
-
-# If not on develop, exit, else we cannot get the list of modified files
-# It is ok to check only when on develop branch
-if [[ "${branch}" -eq 'develop' ]]; then
- echo "Check that a file has been added to /changelog.d"
-else
- echo "Not on develop branch"
- exit 0
-fi
-
-# git status
-
-listOfModifiedFiles=`git diff --name-only HEAD ${branch}`
-
-# echo "List of modified files by this PR:"
-# echo ${listOfModifiedFiles}
-
-
-if [[ ${listOfModifiedFiles} = *"changelog.d"* ]]; then
- echo "A file has been added to /changelog.d!"
-else
- echo "❌ Please add a file describing your changes in /changelog.d. See https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog"
- exit 1
-fi
diff --git a/vector-config/src/main/java/im/vector/app/config/Analytics.kt b/vector-config/src/main/java/im/vector/app/config/Analytics.kt
new file mode 100644
index 0000000000..7fdc78dc8a
--- /dev/null
+++ b/vector-config/src/main/java/im/vector/app/config/Analytics.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.config
+
+/**
+ * The types of analytics Element currently supports.
+ */
+sealed interface Analytics {
+
+ /**
+ * Disables the analytics integrations.
+ */
+ object Disabled : Analytics
+
+ /**
+ * Analytics integration via PostHog.
+ */
+ data class PostHog(
+ /**
+ * The PostHog instance url.
+ */
+ val postHogHost: String,
+
+ /**
+ * The PostHog instance API key.
+ */
+ val postHogApiKey: String,
+
+ /**
+ * A URL to more information about the analytics collection.
+ */
+ val policyLink: String,
+ ) : Analytics
+}
diff --git a/vector-config/src/main/java/im/vector/app/config/Config.kt b/vector-config/src/main/java/im/vector/app/config/Config.kt
index c1413f2e93..b8daa6349e 100644
--- a/vector-config/src/main/java/im/vector/app/config/Config.kt
+++ b/vector-config/src/main/java/im/vector/app/config/Config.kt
@@ -20,6 +20,14 @@ package im.vector.app.config
* Set of flags to configure the application.
*/
object Config {
+
+ // Tchap: The spaces feature is hidden, show all rooms in the home
+ const val SHOW_SPACES = false
+ const val SPACES_SHOW_ALL_IN_HOME = !SHOW_SPACES
+
+ // Tchap: Hide voice message recorder button
+ const val SHOW_VOICE_RECORDER = false
+
/**
* Flag to allow external UnifiedPush distributors to be chosen by the user.
*
@@ -35,5 +43,50 @@ object Config {
* - Changing the value from `false` to `true` will let the user be able to select an external UnifiedPush distributor;
* - Changing the value from `true` to `false` will force the app to return to the background sync / Firebase Push.
*/
- const val ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS = false
+ const val ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS = false // Tchap: Disable UnifiedPush (use Firebase/background sync)
+
+ const val ENABLE_LOCATION_SHARING = false // Tchap: Disable Location Sharing
+ const val LOCATION_MAP_TILER_KEY = "" // Tchap: Disable Location Sharing
+
+ /**
+ * The maximum length of voice messages in milliseconds.
+ */
+ const val VOICE_MESSAGE_LIMIT_MS = 120_000L
+
+ /**
+ * The strategy for sharing device keys.
+ */
+ val KEY_SHARING_STRATEGY = KeySharingStrategy.WhenTyping
+
+ /**
+ * The onboarding flow.
+ */
+ val ONBOARDING_VARIANT = OnboardingVariant.LEGACY // Tchap: Use legacy login flow
+
+ /**
+ * If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
+ * This *must* only be set in trusted environments.
+ */
+ const val HANDLE_CALL_ASSERTED_IDENTITY_EVENTS = false
+
+ const val LOW_PRIVACY_LOG_ENABLE = false
+ const val ENABLE_STRICT_MODE_LOGS = false
+
+ /**
+ * The analytics configuration to use for the Debug build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val DEBUG_ANALYTICS_CONFIG = Analytics.Disabled // Tchap: No analytics
+
+ /**
+ * The analytics configuration to use for the Release build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val RELEASE_ANALYTICS_CONFIG = Analytics.Disabled // Tchap: No analytics
+
+ /**
+ * The analytics configuration to use for the Nightly build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val NIGHTLY_ANALYTICS_CONFIG = Analytics.Disabled // Tchap: No analytics
}
diff --git a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt b/vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
similarity index 50%
rename from vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt
rename to vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
index e1427338b2..51f3d81151 100644
--- a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt
+++ b/vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 New Vector Ltd
+ * Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,17 +16,20 @@
package im.vector.app.config
-import im.vector.app.BuildConfig
-import im.vector.app.features.analytics.AnalyticsConfig
+enum class KeySharingStrategy {
+ /**
+ * Keys will be sent for the first time when the first message is sent.
+ * This is handled by the Matrix SDK so there's no need to do it in Vector.
+ */
+ WhenSendingEvent,
-private val allowedPackageList = listOf(
- "im.vector.app",
- "im.vector.app.nightly",
-)
+ /**
+ * Keys will be sent for the first time when the timeline displayed.
+ */
+ WhenEnteringRoom,
-val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig {
- override val isEnabled = BuildConfig.APPLICATION_ID in allowedPackageList
- override val postHogHost = "https://posthog.hss.element.io"
- override val postHogApiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO"
- override val policyLink = "https://element.io/cookie-policy"
+ /**
+ * Keys will be sent for the first time when a typing started.
+ */
+ WhenTyping
}
diff --git a/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt
new file mode 100644
index 0000000000..ae8cfd1172
--- /dev/null
+++ b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.config
+
+enum class OnboardingVariant {
+ LEGACY,
+ LOGIN_2,
+ FTUE_AUTH
+}
diff --git a/vector/build.gradle b/vector/build.gradle
index cdddef7671..895ee6a175 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -27,6 +27,7 @@ knit {
exclude '**/.gradle/**'
exclude '**/towncrier/template.md'
exclude '**/CHANGES.md'
+ exclude '/node_modules'
}
}
@@ -157,39 +158,15 @@ android {
buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\""
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
- buildConfigField "im.vector.app.features.VectorFeatures.OnboardingVariant", "ONBOARDING_VARIANT", "im.vector.app.features.VectorFeatures.OnboardingVariant.LEGACY"
-
- buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
-
- buildConfigField "Long", "VOICE_MESSAGE_DURATION_LIMIT_MS", "120_000L"
-
- // If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
- // This *must* only be set in trusted environments.
- buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false"
-
// Tchap: Disable Location Sharing
- def enableLocationSharing = false
- buildConfigField "Boolean", "enableLocationSharing", "${enableLocationSharing}"
- resValue "bool", "enable_location_sharing", "${enableLocationSharing}"
- buildConfigField "String", "mapTilerKey", "\"\""
+ resValue "bool", "enable_location_sharing", "false"
// Tchap: The spaces feature is hidden, show all rooms in the home
def showSpaces = false
def showAllInHome = !showSpaces
- buildConfigField "Boolean", "SHOW_SPACES", "${showSpaces}"
resValue "bool", "show_spaces", "${showSpaces}"
- buildConfigField "Boolean", "SPACES_SHOW_ALL_IN_HOME", "${showAllInHome}"
resValue "bool", "spaces_show_all_in_home", "${showAllInHome}"
- // Tchap: Hide voice message recorder button
- buildConfigField "Boolean", "SHOW_VOICE_RECORDER", "false"
-
- // Tchap: Enable add messages reaction
- buildConfigField "Boolean", "SHOW_ADD_MESSAGE_REACTION", "true"
-
- // Tchap: Enable editing messages
- buildConfigField "Boolean", "SHOW_EDIT_MESSAGE", "true"
-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// Tchap: Disable universalApk
@@ -278,12 +255,6 @@ android {
// resValue "string", "app_name", "Element dbg"
// resValue "color", "launcher_background", "#0DBD8B"
- buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
- // Set to true if you want to enable strict mode in debug
- buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-
- // Tchap: Disable the location sharing
- buildConfigField "Boolean", "ENABLE_LIVE_LOCATION_SHARING", "false"
// Tchap: Show developer mode only in debug
resValue "bool", "developer_mode_visible", "true"
@@ -298,13 +269,9 @@ android {
// resValue "string", "app_name", "Element"
// resValue "color", "launcher_background", "#0DBD8B"
- buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
- buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-
// Tchap: Show developer mode only in debug
resValue "bool", "developer_mode_visible", "false"
- // When updating this block, please also update the same block in the `nightly` buildType below
postprocessing {
removeUnusedCode true
removeUnusedResources true
@@ -369,7 +336,6 @@ android {
isDefault = true
resValue "bool", "isGplay", "true"
- buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
}
@@ -378,7 +344,6 @@ android {
dimension "store"
resValue "bool", "isGplay", "false"
- buildConfigField "boolean", "ALLOW_FCM_USE", "false"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
}
@@ -606,7 +571,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho:1.6.0'
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
// FlowBinding
implementation libs.github.flowBinding
@@ -618,6 +583,9 @@ dependencies {
implementation libs.airbnb.epoxyPaging
implementation libs.airbnb.mavericks
+ // Snap Helper https://github.com/rubensousa/GravitySnapHelper
+ implementation 'com.github.rubensousa:gravitysnaphelper:2.2.2'
+
// Nightly
// API-only library
gplayImplementation libs.google.appdistributionApi
@@ -758,44 +726,44 @@ dependencies {
// Tchap: We had to exclude fbjni for withVoip, the library is already include in jitsi library
// Flipper, debug builds only
- gplayBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- gplayTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- gplayDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidBtchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidDevTchapWithvoipWithpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- gplayBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- gplayDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- gplayTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- gplayTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ gplayTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ gplayTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidBtchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidDevTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
- fdroidTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni'}
- fdroidTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) {exclude group: 'com.facebook.fbjni', module: 'fbjni'}
+ fdroidTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipper) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
+ fdroidTchapWithvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin) { exclude group: 'com.facebook.fbjni', module: 'fbjni' }
gplayBtchapWithoutvoipWithoutpinningDebugImplementation(libs.flipper.flipper)
gplayBtchapWithoutvoipWithoutpinningDebugImplementation(libs.flipper.flipperNetworkPlugin)
@@ -837,7 +805,7 @@ dependencies {
debugImplementation 'com.facebook.soloader:soloader:0.10.4'
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0"
-
+
// Activate when you want to check for leaks, from time to time.
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
@@ -862,4 +830,5 @@ dependencies {
androidTestImplementation libs.mockk.mockkAndroid
androidTestUtil libs.androidx.orchestrator
debugImplementation libs.androidx.fragmentTesting
+ androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10"
}
diff --git a/vector/lint.xml b/vector/lint.xml
index 225f1db517..023b9dad7c 100644
--- a/vector/lint.xml
+++ b/vector/lint.xml
@@ -108,6 +108,7 @@
+
diff --git a/vector/src/androidTest/java/im/vector/app/CantVerifyTest.kt b/vector/src/androidTest/java/im/vector/app/CantVerifyTest.kt
index ba844e56b7..90ed8e5948 100644
--- a/vector/src/androidTest/java/im/vector/app/CantVerifyTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/CantVerifyTest.kt
@@ -25,17 +25,22 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import im.vector.app.features.MainActivity
import im.vector.app.ui.robot.ElementRobot
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
+import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import java.util.UUID
@RunWith(AndroidJUnit4::class)
@LargeTest
+@Ignore("Tchap: Secure Backup is disabled, so this test cannot succeed")
class CantVerifyTest : VerificationTestBase() {
@get:Rule
- val activityRule = ActivityScenarioRule(MainActivity::class.java)
+ val testRule = RuleChain
+ .outerRule(ActivityScenarioRule(MainActivity::class.java))
+ .around(ClearCurrentSessionRule())
private val elementRobot = ElementRobot()
var userName: String = "loginTest_${UUID.randomUUID()}"
diff --git a/vector/src/androidTest/java/im/vector/app/ClearCurrentSessionRule.kt b/vector/src/androidTest/java/im/vector/app/ClearCurrentSessionRule.kt
new file mode 100644
index 0000000000..735e96c1e0
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ClearCurrentSessionRule.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app
+
+import android.content.Context
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.test.platform.app.InstrumentationRegistry
+import im.vector.app.features.analytics.store.AnalyticsStore
+import kotlinx.coroutines.runBlocking
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+import kotlin.reflect.KClass
+
+/**
+ * A TestRule to reset and clear the current Session.
+ * If a Session is active it will be signed out and cleared from the ActiveSessionHolder.
+ * The VectorPreferences and AnalyticsDatastore are also cleared in an attempt to recreate a fresh base.
+ */
+class ClearCurrentSessionRule : TestWatcher() {
+ override fun apply(base: Statement, description: Description): Statement {
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ runBlocking {
+ reflectAnalyticDatastore(context).edit { it.clear() }
+ runCatching {
+ val holder = (context.applicationContext as VectorApplication).activeSessionHolder
+ holder.getSafeActiveSession()?.signOutService()?.signOut(true)
+ (context.applicationContext as VectorApplication).vectorPreferences.clearPreferences()
+ holder.clearActiveSession()
+ }
+ }
+ return super.apply(base, description)
+ }
+}
+
+private fun KClass<*>.asTopLevel() = Class.forName("${qualifiedName}Kt")
+
+/**
+ * Fetches the top level, private [Context.dataStore] extension property from [im.vector.app.features.analytics.store.AnalyticsStore]
+ * via reflection to avoid exposing property to all callers.
+ */
+@Suppress("UNCHECKED_CAST")
+private fun reflectAnalyticDatastore(context: Context): DataStore {
+ val klass = AnalyticsStore::class.asTopLevel()
+ val method = klass.getMethod("access\$getDataStore", Context::class.java)
+ return method.invoke(klass, context) as DataStore
+}
diff --git a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelperTests.kt b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelperTests.kt
index 53c154ae30..30520dd44f 100644
--- a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelperTests.kt
+++ b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelperTests.kt
@@ -31,7 +31,6 @@ import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import im.vector.app.TestBuildVersionSdkIntProvider
import im.vector.app.features.pin.lockscreen.configuration.LockScreenConfiguration
-import im.vector.app.features.pin.lockscreen.configuration.LockScreenConfiguratorProvider
import im.vector.app.features.pin.lockscreen.configuration.LockScreenMode
import im.vector.app.features.pin.lockscreen.crypto.LockScreenCryptoConstants
import im.vector.app.features.pin.lockscreen.crypto.LockScreenKeyRepository
@@ -40,6 +39,7 @@ import im.vector.app.features.pin.lockscreen.ui.fallbackprompt.FallbackBiometric
import im.vector.app.features.pin.lockscreen.utils.DevicePromptCheck
import io.mockk.clearAllMocks
import io.mockk.every
+import io.mockk.justRun
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.mockkStatic
@@ -54,8 +54,10 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
+import org.amshove.kluent.coInvoking
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
+import org.amshove.kluent.shouldThrow
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
@@ -239,36 +241,35 @@ class BiometricHelperTests {
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.R) // Due to some issues with mockk and CryptoObject initialization
- fun authenticateCreatesSystemKeyIfNeededOnSuccessOnAndroidM() = runTest {
+ fun enableAuthenticationDeletesSystemKeyOnFailure() = runTest {
buildVersionSdkIntProvider.value = Build.VERSION_CODES.M
- every { lockScreenKeyRepository.isSystemKeyValid() } returns true
val mockAuthChannel = Channel(capacity = 1)
val biometricUtils = spyk(createBiometricHelper(createDefaultConfiguration(isBiometricsEnabled = true))) {
every { createAuthChannel() } returns mockAuthChannel
every { authenticateWithPromptInternal(any(), any(), any()) } returns mockk()
}
+ justRun { lockScreenKeyRepository.deleteSystemKey() }
val latch = CountDownLatch(1)
val intent = Intent(InstrumentationRegistry.getInstrumentation().targetContext, LockScreenTestActivity::class.java)
ActivityScenario.launch(intent).onActivity { activity ->
activity.lifecycleScope.launch {
+ val exception = IllegalStateException("Some error")
launch {
- mockAuthChannel.send(true)
- mockAuthChannel.close()
+ mockAuthChannel.close(exception)
}
- biometricUtils.authenticate(activity).collect()
+ coInvoking { biometricUtils.enableAuthentication(activity).collect() } shouldThrow exception
latch.countDown()
}
}
latch.await(1, TimeUnit.SECONDS)
- verify { lockScreenKeyRepository.ensureSystemKey() }
+ verify { lockScreenKeyRepository.deleteSystemKey() }
}
private fun createBiometricHelper(configuration: LockScreenConfiguration): BiometricHelper {
val context = InstrumentationRegistry.getInstrumentation().targetContext
- val configProvider = LockScreenConfiguratorProvider(configuration)
- return BiometricHelper(context, lockScreenKeyRepository, configProvider, biometricManager, buildVersionSdkIntProvider)
+ return BiometricHelper(configuration, context, lockScreenKeyRepository, biometricManager, buildVersionSdkIntProvider)
}
private fun createDefaultConfiguration(
diff --git a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/KeyStoreCryptoTests.kt b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/KeyStoreCryptoTests.kt
index 6e02cc0262..1712ec889e 100644
--- a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/KeyStoreCryptoTests.kt
+++ b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/KeyStoreCryptoTests.kt
@@ -18,6 +18,7 @@ package im.vector.app.features.pin.lockscreen.crypto
import android.os.Build
import android.security.keystore.KeyPermanentlyInvalidatedException
+import android.security.keystore.UserNotAuthenticatedException
import androidx.test.platform.app.InstrumentationRegistry
import im.vector.app.TestBuildVersionSdkIntProvider
import io.mockk.every
@@ -69,10 +70,12 @@ class KeyStoreCryptoTests {
runCatching { keyStoreCrypto.ensureKey() }
keyStoreCrypto.hasValidKey() shouldBe true
- val exception = KeyPermanentlyInvalidatedException()
- every { secretStoringUtils.getEncryptCipher(any()) } throws exception
+ val keyInvalidatedException = KeyPermanentlyInvalidatedException()
+ every { secretStoringUtils.getEncryptCipher(any()) } throws keyInvalidatedException
+ keyStoreCrypto.hasValidKey() shouldBe false
- runCatching { keyStoreCrypto.ensureKey() }
+ val userNotAuthenticatedException = UserNotAuthenticatedException()
+ every { secretStoringUtils.getEncryptCipher(any()) } throws userNotAuthenticatedException
keyStoreCrypto.hasValidKey() shouldBe false
}
diff --git a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/LockScreenKeyRepositoryTests.kt b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/LockScreenKeyRepositoryTests.kt
index 924dbfee9e..8d14ca9153 100644
--- a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/LockScreenKeyRepositoryTests.kt
+++ b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/crypto/LockScreenKeyRepositoryTests.kt
@@ -17,8 +17,6 @@
package im.vector.app.features.pin.lockscreen.crypto
import androidx.test.platform.app.InstrumentationRegistry
-import im.vector.app.features.pin.lockscreen.crypto.migrations.LegacyPinCodeMigrator
-import im.vector.app.features.settings.VectorPreferences
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
@@ -44,8 +42,6 @@ class LockScreenKeyRepositoryTests {
}
private lateinit var lockScreenKeyRepository: LockScreenKeyRepository
- private val legacyPinCodeMigrator: LegacyPinCodeMigrator = mockk(relaxed = true)
- private val vectorPreferences: VectorPreferences = mockk(relaxed = true)
private val keyStore: KeyStore by lazy {
KeyStore.getInstance(LockScreenCryptoConstants.ANDROID_KEY_STORE).also { it.load(null) }
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
index e72535c116..77b238acaf 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
@@ -22,19 +22,26 @@ import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
+import androidx.test.platform.app.InstrumentationRegistry
import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertDisabled
import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertEnabled
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import im.vector.app.R
+import im.vector.app.config.OnboardingVariant
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.DefaultVectorFeatures
+import im.vector.app.features.debug.features.DebugVectorFeatures
import im.vector.app.waitForView
class OnboardingRobot {
- private val defaultVectorFeatures = DefaultVectorFeatures()
+ // Tchap: Use different onboarding variant to run the tests
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val defaultVectorFeatures = DebugVectorFeatures(context, DefaultVectorFeatures()).apply {
+ overrideEnum(OnboardingVariant.FTUE_AUTH, OnboardingVariant::class)
+ }
fun crawl() {
waitUntilViewVisible(withId(R.id.loginSplashSubmit))
diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
index 8fe65bd387..d7e402c4dc 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
@@ -70,6 +70,11 @@ class DebugFeaturesStateFactory @Inject constructor(
key = DebugFeatureKeys.allowExternalUnifiedPushDistributors,
factory = VectorFeatures::allowExternalUnifiedPushDistributors
),
+ createBooleanFeature(
+ label = "Enable Live Location Sharing",
+ key = DebugFeatureKeys.liveLocationSharing,
+ factory = VectorFeatures::isLocationSharingEnabled
+ ),
createBooleanFeature(
label = "Force usage of OpusEncoder library",
key = DebugFeatureKeys.forceUsageOfOpusEncoder,
diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
index 23aad65653..031ff11d59 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
@@ -24,6 +24,7 @@ import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
+import im.vector.app.config.OnboardingVariant
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.VectorFeatures
import kotlinx.coroutines.flow.first
@@ -39,8 +40,8 @@ class DebugVectorFeatures(
private val dataStore = context.dataStore
- override fun onboardingVariant(): VectorFeatures.OnboardingVariant {
- return readPreferences().getEnum() ?: vectorFeatures.onboardingVariant()
+ override fun onboardingVariant(): OnboardingVariant {
+ return readPreferences().getEnum() ?: vectorFeatures.onboardingVariant()
}
override fun isOnboardingAlreadyHaveAccountSplashEnabled(): Boolean = read(DebugFeatureKeys.onboardingAlreadyHaveAnAccount)
@@ -66,6 +67,9 @@ class DebugVectorFeatures(
override fun isScreenSharingEnabled(): Boolean = read(DebugFeatureKeys.screenSharing)
?: vectorFeatures.isScreenSharingEnabled()
+ override fun isLocationSharingEnabled(): Boolean = read(DebugFeatureKeys.liveLocationSharing)
+ ?: vectorFeatures.isLocationSharingEnabled()
+
override fun forceUsageOfOpusEncoder(): Boolean = read(DebugFeatureKeys.forceUsageOfOpusEncoder)
?: vectorFeatures.forceUsageOfOpusEncoder()
diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index f9f1a4bf3f..0b5f0c6f63 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -351,7 +351,7 @@
-
+
@@ -383,7 +383,7 @@
diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt
new file mode 100644
index 0000000000..d9f002be37
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app
+
+import androidx.lifecycle.DefaultLifecycleObserver
+import arrow.core.Option
+import kotlinx.coroutines.flow.Flow
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+
+/**
+ * Gets info about the current space the user has navigated to, any space backstack they may have
+ * and handles switching to different spaces.
+ */
+interface SpaceStateHandler : DefaultLifecycleObserver {
+
+ /**
+ * Gets the current space the current user has navigated to.
+ *
+ * @return null if the user is not in
+ */
+ fun getCurrentSpace(): RoomSummary?
+
+ /**
+ * Sets the new space the current user is navigating to.
+ *
+ * @param spaceId the id of the space being navigated to
+ * @param session the current active session
+ * @param persistNow if true, the current space will immediately be persisted in shared prefs
+ * @param isForwardNavigation whether this navigation is a forward action to properly handle backstack
+ */
+ fun setCurrentSpace(
+ spaceId: String?,
+ session: Session? = null,
+ persistNow: Boolean = false,
+ isForwardNavigation: Boolean = true,
+ )
+
+ /**
+ * Gets the current backstack of spaces (via their id).
+ *
+ * null may be an entry in the ArrayDeque to indicate the root space (All Chats)
+ */
+ fun getSpaceBackstack(): ArrayDeque
+
+ /**
+ * Gets a flow of the selected space for clients to react immediately to space changes.
+ */
+ fun getSelectedSpaceFlow(): Flow