mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
362 Commits
v1.4.30
...
bug/eric/f
Author | SHA1 | Date | |
---|---|---|---|
|
6121468422 | ||
|
ac0af80e48 | ||
|
519855445e | ||
|
0dcab56e34 | ||
|
66092cfa25 | ||
|
7a30c72828 | ||
|
0be7f3c356 | ||
|
cc74dcfb90 | ||
|
aef4c14b20 | ||
|
5e308e02a0 | ||
|
4485673db9 | ||
|
2c82bf1990 | ||
|
593c6e4b54 | ||
|
8857decc87 | ||
|
6031c50313 | ||
|
6c860710bd | ||
|
520d6f9b97 | ||
|
c5e601d726 | ||
|
b6bcefbb92 | ||
|
4fedafc1be | ||
|
f0dc938fd0 | ||
|
27de9230b1 | ||
|
446bf7e0aa | ||
|
ea465a1b86 | ||
|
6089d24409 | ||
|
6ac88a9420 | ||
|
74d99b156f | ||
|
8b0fba2ef5 | ||
|
680dc207c0 | ||
|
1389262c3f | ||
|
08fff48065 | ||
|
8a4bd0c467 | ||
|
6c767de148 | ||
|
6c65b0a9e0 | ||
|
d92cf04b6f | ||
|
54d8c9de48 | ||
|
314b077fbd | ||
|
d365ccdc21 | ||
|
19261ab2d0 | ||
|
ecfa7db07d | ||
|
62f7b40a3e | ||
|
9eb6969456 | ||
|
a1152ff72c | ||
|
a124b514b8 | ||
|
969689cdb9 | ||
|
d702210f26 | ||
|
ef3615594b | ||
|
3b7fd2dfde | ||
|
971ad26deb | ||
|
b58aeaad9e | ||
|
e0e21d4282 | ||
|
2364b68907 | ||
|
5bb67ec253 | ||
|
d9fbc4a011 | ||
|
292f6622bd | ||
|
8667de423a | ||
|
ef2aa6f829 | ||
|
60eb9b428d | ||
|
8f218ce773 | ||
|
2158661e77 | ||
|
fa8f72c909 | ||
|
616c16f8c6 | ||
|
ce23303b97 | ||
|
439224e4de | ||
|
0515303c8c | ||
|
fde0039027 | ||
|
5d1750675b | ||
|
73e437de0b | ||
|
cd929a203e | ||
|
bcd038deb2 | ||
|
5120cf7a76 | ||
|
3a9aa7472a | ||
|
a2c39c079a | ||
|
89f31b093e | ||
|
de240b7318 | ||
|
6526cf3c2e | ||
|
2764a6e103 | ||
|
3ff9ab1bc8 | ||
|
250ee1faa1 | ||
|
12405527e1 | ||
|
36c69a46fd | ||
|
31a350eea7 | ||
|
aecf460c96 | ||
|
fcc7bbadfa | ||
|
defd848363 | ||
|
527bcf2e6f | ||
|
fd37b31c44 | ||
|
b9fa4ddfc8 | ||
|
ed00685514 | ||
|
1ebc2a9a8c | ||
|
db1d0daec0 | ||
|
fb0b38bb49 | ||
|
e81da5d8b4 | ||
|
358ec5a722 | ||
|
e87eefb319 | ||
|
ddaf5397b1 | ||
|
ce4ab78f13 | ||
|
9505d196e4 | ||
|
f9a6839f72 | ||
|
a2768ccab7 | ||
|
ac6b0a908a | ||
|
53e396d337 | ||
|
fe61fa844e | ||
|
d7949307a4 | ||
|
f94aad65dd | ||
|
6045eac87a | ||
|
af04221ad9 | ||
|
65b7a31728 | ||
|
9888e15f2a | ||
|
cc59b9e695 | ||
|
dfc8526b47 | ||
|
2f4725cfe9 | ||
|
6e1e31bac1 | ||
|
58d47df37b | ||
|
319ec6fbf4 | ||
|
045398d06f | ||
|
ed3b73a989 | ||
|
9892c66d27 | ||
|
7b61460fa2 | ||
|
f2c3b5cb43 | ||
|
b2d1915227 | ||
|
0c61595ace | ||
|
f605e0c479 | ||
|
02286b96b0 | ||
|
8156a646a1 | ||
|
19c8b2a630 | ||
|
e02cf61f2f | ||
|
7e7b98a3c1 | ||
|
dd496dc1a3 | ||
|
ac047afd27 | ||
|
77ae291c15 | ||
|
ec9199cb18 | ||
|
e15e941e49 | ||
|
fde0d81c1e | ||
|
2aac0c9d64 | ||
|
05816d00ae | ||
|
ee1f294327 | ||
|
a41ad6625e | ||
|
721c4c0d9c | ||
|
804880cc9c | ||
|
8cbdd6e130 | ||
|
4a3b6baaf7 | ||
|
dbbdc1791a | ||
|
7b96597d56 | ||
|
4af4f3f88c | ||
|
a56d8a23f5 | ||
|
f33e2fd656 | ||
|
c2fbb74e4b | ||
|
20b3dbc6e6 | ||
|
756570793f | ||
|
1ffa02c287 | ||
|
1bf36dce92 | ||
|
41d859dc5b | ||
|
81897a179e | ||
|
e6508e8a5a | ||
|
0567fa3e53 | ||
|
2683e9209b | ||
|
03afd2932c | ||
|
5864ce4348 | ||
|
90f2b93763 | ||
|
a821f34fc0 | ||
|
b375dd14f7 | ||
|
0506c9abfd | ||
|
ff71e69b0e | ||
|
2dc92caa30 | ||
|
f0bd5dc2dd | ||
|
619cb29707 | ||
|
30a8f22028 | ||
|
68e55c01f9 | ||
|
65c6e578eb | ||
|
2b8632ebe7 | ||
|
72377c9e7e | ||
|
ec5f874a81 | ||
|
6590cf5524 | ||
|
008e07d03e | ||
|
a30076a2ab | ||
|
6972622bc6 | ||
|
e0e06c6ac8 | ||
|
87ca9606b3 | ||
|
6572a1a331 | ||
|
b83acf373d | ||
|
8f91278d1a | ||
|
64c25f073c | ||
|
81cba3d275 | ||
|
018772ca9a | ||
|
8b8a4f3d7b | ||
|
09a91c4541 | ||
|
e26d87c73d | ||
|
8470ac9731 | ||
|
b6582c4144 | ||
|
f40cf13048 | ||
|
99de618bed | ||
|
dd69b254f9 | ||
|
9a97e0bf61 | ||
|
a4ea47e740 | ||
|
825ba77bb2 | ||
|
79e6dd074a | ||
|
b0f73b029c | ||
|
7bf8a41959 | ||
|
b73c097f3c | ||
|
b4ed380caf | ||
|
5d183654b1 | ||
|
b625d6a9bc | ||
|
c6e263a6d3 | ||
|
ee553d6693 | ||
|
bfd9dcbca2 | ||
|
4bff816056 | ||
|
aa24debd87 | ||
|
8aaf185a8e | ||
|
55d8b6a819 | ||
|
ac8597e745 | ||
|
e2ed4b4ae1 | ||
|
ab4eda18bf | ||
|
a53de92b10 | ||
|
2ee52f2062 | ||
|
d1a63ccd2d | ||
|
3c1e183ed6 | ||
|
9b1def3c1d | ||
|
8b9d1bb0d8 | ||
|
cb59d82846 | ||
|
fe1019f29f | ||
|
3d207f93f1 | ||
|
c07296c94d | ||
|
cceac66504 | ||
|
18943e3453 | ||
|
df02f505ad | ||
|
d42c27bfe0 | ||
|
811b2e8c75 | ||
|
9fe3fc69dd | ||
|
cc4aae0f4a | ||
|
b6d052e58d | ||
|
56afac26ad | ||
|
012485b8e3 | ||
|
f14aabcd22 | ||
|
e795e9da52 | ||
|
87a8c786f7 | ||
|
274b1a149c | ||
|
c848615636 | ||
|
b0a9b482e7 | ||
|
1497650146 | ||
|
927b51413c | ||
|
3fe7a9d8d5 | ||
|
c99f67bea4 | ||
|
ba5d6c9108 | ||
|
7d120f94f6 | ||
|
5d30026726 | ||
|
c926b4cc69 | ||
|
1ef809c633 | ||
|
e311d0e469 | ||
|
2c10d9dcaa | ||
|
f44d8b0b20 | ||
|
72e2951c3e | ||
|
9781656c1d | ||
|
4f71741107 | ||
|
74c9a71cbd | ||
|
49ad37a7f6 | ||
|
0944b2ff39 | ||
|
004f40bff5 | ||
|
8571fd0ba9 | ||
|
c616229d53 | ||
|
a8df1af6fd | ||
|
be696f5a5c | ||
|
1411fdd99f | ||
|
e1c572e46c | ||
|
fde2aee69a | ||
|
cf5745e966 | ||
|
0c4c695b9c | ||
|
e0349b27ed | ||
|
9114630bba | ||
|
3725921400 | ||
|
9ea0f88181 | ||
|
cf247eafb7 | ||
|
dbe5b35ad4 | ||
|
6b754f3e03 | ||
|
410a7b525f | ||
|
fedbe048ba | ||
|
3845e1435c | ||
|
21e88efaff | ||
|
6671a100ad | ||
|
91b0465caa | ||
|
68cd7d487a | ||
|
302edb44dc | ||
|
ddaf1128ac | ||
|
d116d98080 | ||
|
406a67827c | ||
|
725ed00759 | ||
|
5e19838108 | ||
|
fa8f110579 | ||
|
8e7e320e40 | ||
|
a83f714657 | ||
|
c20c3a741a | ||
|
d60695806f | ||
|
c41f0dd0cf | ||
|
619e5dd7d1 | ||
|
3d722118ca | ||
|
b161e5eb2e | ||
|
07dc0d2e54 | ||
|
e9aab6331a | ||
|
59f00cd196 | ||
|
c863b90d42 | ||
|
c7d5ceca5d | ||
|
4f5ad816f1 | ||
|
79ea66890f | ||
|
3a5c139759 | ||
|
fb67499657 | ||
|
66fa285910 | ||
|
4d62e75c65 | ||
|
cc6dad3fce | ||
|
b77475a3d9 | ||
|
036521af94 | ||
|
a062093acf | ||
|
630a981864 | ||
|
56691f613e | ||
|
a52a2504ef | ||
|
67d4afa012 | ||
|
ca49cce759 | ||
|
2c5504ffce | ||
|
2b58c42c8b | ||
|
b2e64e6265 | ||
|
d49f104332 | ||
|
d304624878 | ||
|
bb9459fcab | ||
|
590f99a5c2 | ||
|
e6addd1319 | ||
|
a11d5ebdd9 | ||
|
5b9c7c3b27 | ||
|
4958b8ae7b | ||
|
c4831510ac | ||
|
a32a78751a | ||
|
87a0957d9a | ||
|
e77688b3f4 | ||
|
3c8401bc24 | ||
|
d3a1783e57 | ||
|
9a981bb1d5 | ||
|
7de82e0204 | ||
|
7334d909d5 | ||
|
fb82b1d1ce | ||
|
f3ad9e38c3 | ||
|
f56c315207 | ||
|
5958559186 | ||
|
a5039287b2 | ||
|
3df337fa07 | ||
|
d8668f70bc | ||
|
8b220de952 | ||
|
a909779e08 | ||
|
d8fdaf0477 | ||
|
1d77f99148 | ||
|
f0ae458a54 | ||
|
9a649b6093 | ||
|
f770ae0653 | ||
|
49992f682e | ||
|
f0165f69d3 | ||
|
fbdbfb6be2 | ||
|
e4c8c88cee | ||
|
4dccff4d78 | ||
|
2d761385a1 | ||
|
62f2fe1c16 | ||
|
40f8d94954 | ||
|
b4f833cb0d | ||
|
50b7f3ef2c | ||
|
6ed36e804b | ||
|
0dc80db9b7 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -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:
|
||||
debug:
|
||||
@@ -36,7 +34,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:
|
||||
@@ -61,7 +59,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Assemble GPlay unsigned apk
|
||||
run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||
run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
- name: Upload Gplay unsigned APKs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
20
.github/workflows/danger.yml
vendored
Normal file
20
.github/workflows/danger.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
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 }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@@ -1,5 +1,8 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request: { }
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
|
8
.github/workflows/nightly.yml
vendored
8
.github/workflows/nightly.yml
vendored
@@ -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:
|
||||
@@ -40,7 +38,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 }}
|
||||
|
6
.github/workflows/post-pr.yml
vendored
6
.github/workflows/post-pr.yml
vendored
@@ -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:
|
||||
|
||||
|
194
.github/workflows/quality.yml
vendored
194
.github/workflows/quality.yml
vendored
@@ -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:
|
||||
check:
|
||||
@@ -29,80 +27,52 @@ 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\/element-android\/element-android\//\`<br\/>\`/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
|
||||
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:
|
||||
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
|
||||
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 }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
|
||||
dependency-analysis:
|
||||
@@ -122,107 +92,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: [ Gplay, Fdroid ]
|
||||
# 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 }}
|
||||
|
22
.github/workflows/tests.yml
vendored
22
.github/workflows/tests.yml
vendored
@@ -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,13 +65,13 @@ 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
|
||||
- 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
|
||||
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 }}
|
||||
|
||||
@@ -114,5 +112,5 @@ 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
|
||||
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -17,3 +17,8 @@
|
||||
/fastlane/report.xml
|
||||
|
||||
/**/build
|
||||
|
||||
# Added by yarn
|
||||
/package.json
|
||||
/yarn.lock
|
||||
/node_modules
|
||||
|
18
.travis.yml
18
.travis.yml
@@ -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
|
44
CHANGES.md
44
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)
|
||||
=======================================
|
||||
|
||||
|
39
Gemfile.lock
39
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
|
||||
|
15
build.gradle
15
build.gradle
@@ -24,13 +24,13 @@ buildscript {
|
||||
classpath libs.gradle.gradlePlugin
|
||||
classpath libs.gradle.kotlinPlugin
|
||||
classpath libs.gradle.hiltPlugin
|
||||
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.2'
|
||||
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.3'
|
||||
classpath 'com.google.gms:google-services:4.3.13'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513'
|
||||
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.12.0"
|
||||
}
|
||||
|
||||
// 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",
|
||||
@@ -146,6 +151,8 @@ allprojects {
|
||||
"experimental:comment-wrapping",
|
||||
// - A KDoc comment after any other element on the same line must be separated by a new line
|
||||
"experimental:kdoc-wrapping",
|
||||
// Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt"
|
||||
"string-template",
|
||||
]
|
||||
}
|
||||
|
||||
|
1
changelog.d/5525.wip
Normal file
1
changelog.d/5525.wip
Normal file
@@ -0,0 +1 @@
|
||||
Create DM room only on first message - Trigger the flow when the "Direct Message" action is selected from the room member details screen
|
1
changelog.d/5974.misc
Normal file
1
changelog.d/5974.misc
Normal file
@@ -0,0 +1 @@
|
||||
Removes the Login2 proof of concept - replaced by the FTUE changes
|
1
changelog.d/6505.wip
Normal file
1
changelog.d/6505.wip
Normal file
@@ -0,0 +1 @@
|
||||
added filter tabs for new App layout's Home screen
|
1
changelog.d/6645.misc
Normal file
1
changelog.d/6645.misc
Normal file
@@ -0,0 +1 @@
|
||||
Enable auto-capitalization for Room creation Title field
|
1
changelog.d/6693.feature
Normal file
1
changelog.d/6693.feature
Normal file
@@ -0,0 +1 @@
|
||||
Adds New App Layout FABs (hidden behind feature flag)
|
1
changelog.d/6746.feature
Normal file
1
changelog.d/6746.feature
Normal file
@@ -0,0 +1 @@
|
||||
[Notification] - Handle creation of notification for live location and poll start
|
1
changelog.d/6749.wip
Normal file
1
changelog.d/6749.wip
Normal file
@@ -0,0 +1 @@
|
||||
Adds space list bottom sheet for new app layout
|
1
changelog.d/6783.misc
Normal file
1
changelog.d/6783.misc
Normal file
@@ -0,0 +1 @@
|
||||
Decouples the variant logic from the vector module
|
1
changelog.d/6786.misc
Normal file
1
changelog.d/6786.misc
Normal file
@@ -0,0 +1 @@
|
||||
Add a developer setting to enable LeakCanary at runtime
|
1
changelog.d/6795.wip
Normal file
1
changelog.d/6795.wip
Normal file
@@ -0,0 +1 @@
|
||||
Makes toolbar switch title based on space in New App Layout
|
1
changelog.d/6798.wip
Normal file
1
changelog.d/6798.wip
Normal file
@@ -0,0 +1 @@
|
||||
[Devices management] Add a feature flag and empty screen for future new layout
|
1
changelog.d/6799.misc
Normal file
1
changelog.d/6799.misc
Normal file
@@ -0,0 +1 @@
|
||||
[Create Room] Reduce some boilerplate with room state event contents
|
1
changelog.d/6806.wip
Normal file
1
changelog.d/6806.wip
Normal file
@@ -0,0 +1 @@
|
||||
[Devices management] Other sessions section in new layout
|
1
changelog.d/6808.misc
Normal file
1
changelog.d/6808.misc
Normal file
@@ -0,0 +1 @@
|
||||
[Call] Memory leak after a call
|
1
changelog.d/6843.misc
Normal file
1
changelog.d/6843.misc
Normal file
@@ -0,0 +1 @@
|
||||
Fix some string template
|
@@ -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.157.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.2"
|
||||
|
||||
// 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",
|
||||
|
@@ -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',
|
||||
@@ -106,7 +107,9 @@ ext.groups = [
|
||||
'com.pinterest.ktlint',
|
||||
'com.posthog.android',
|
||||
'com.squareup',
|
||||
'com.squareup.curtains',
|
||||
'com.squareup.duktape',
|
||||
'com.squareup.leakcanary',
|
||||
'com.squareup.moshi',
|
||||
'com.squareup.okhttp3',
|
||||
'com.squareup.okio',
|
||||
@@ -125,6 +128,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',
|
||||
|
105
docs/danger.md
Normal file
105
docs/danger.md
Normal file
@@ -0,0 +1,105 @@
|
||||
## Danger
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [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)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## 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 does not modify frozen classes
|
||||
- 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 <PR_URL> --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 <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
||||
bundle exec danger-kotlin pr <PR_URL> --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.
|
||||
|
||||
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
|
||||
|
||||
- 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
|
@@ -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.
|
||||
|
2
fastlane/metadata/android/en-US/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40104310.txt
Normal file
@@ -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
|
2
fastlane/metadata/android/en-US/changelogs/40104320.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40104320.txt
Normal 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
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=97a52d145762adc241bad7fd18289bf7f6801e08ece6badf80402fe2b9f250b1
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
|
||||
distributionSha256Sum=db9c8211ed63f61f60292c69e80d89196f9eb36665e369e7f00ac4cc841c2219
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@@ -0,0 +1,4 @@
|
||||
<vector android:height="22dp" android:viewportHeight="22"
|
||||
android:viewportWidth="22" android:width="22dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#737D8C" android:fillType="evenOdd" android:pathData="M16.999,14.899C18.07,13.407 18.7,11.577 18.7,9.6C18.7,4.574 14.626,0.5 9.6,0.5C4.574,0.5 0.5,4.574 0.5,9.6C0.5,14.626 4.574,18.7 9.6,18.7C11.577,18.7 13.406,18.07 14.899,16.999C14.941,17.055 14.988,17.109 15.039,17.161L18.939,21.061C19.525,21.646 20.475,21.646 21.06,21.061C21.646,20.475 21.646,19.525 21.06,18.939L17.16,15.039C17.109,14.988 17.055,14.941 16.999,14.899ZM15.7,9.6C15.7,12.969 12.969,15.7 9.6,15.7C6.231,15.7 3.5,12.969 3.5,9.6C3.5,6.231 6.231,3.5 9.6,3.5C12.969,3.5 15.7,6.231 15.7,9.6Z"/>
|
||||
</vector>
|
@@ -71,4 +71,7 @@
|
||||
<dimen name="location_sharing_compass_button_margin_horizontal">8dp</dimen>
|
||||
<dimen name="location_sharing_live_duration_choice_margin_horizontal">12dp</dimen>
|
||||
<dimen name="location_sharing_live_duration_choice_margin_vertical">22dp</dimen>
|
||||
|
||||
<!-- Material 3 -->
|
||||
<dimen name="collapsing_toolbar_layout_medium_size">112dp</dimen>
|
||||
</resources>
|
||||
|
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="DevicesListHeaderView">
|
||||
<attr name="devicesListHeaderTitle" format="string" />
|
||||
<attr name="devicesListHeaderDescription" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="LocationLiveEndedBannerView">
|
||||
<declare-styleable name="LiveLocationEndedBannerView">
|
||||
<attr name="locLiveEndedBkgWithAlpha" format="boolean" />
|
||||
<attr name="locLiveEndedIconMarginStart" format="dimension" />
|
||||
</declare-styleable>
|
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="MapLoadingErrorView">
|
||||
<attr name="mapErrorDescription" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
@@ -65,4 +65,8 @@
|
||||
<item name="colorPrimary">?colorOnPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Vector.FloatingActionButton" parent="Widget.MaterialComponents.FloatingActionButton">
|
||||
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.Material3.FloatingActionButton</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="TextAppearance.Vector.Subtitle.Medium.DevicesManagement">
|
||||
<item name="android:textColor">?vctr_content_primary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Vector.Body.DevicesManagement">
|
||||
<item name="android:textColor">?vctr_content_secondary</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Widget.Vector.Button.Text.OnPrimary.LocationLive">
|
||||
<style name="Widget.Vector.Button.Text.OnPrimary.LiveLocation">
|
||||
<item name="android:foreground">?selectableItemBackground</item>
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
@@ -12,7 +12,7 @@
|
||||
<item name="android:insetLeft">8dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Vector.Button.Text.LocationLive">
|
||||
<style name="Widget.Vector.Button.Text.LiveLocation">
|
||||
<item name="android:foreground">?selectableItemBackground</item>
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Vector.Body.Medium</item>
|
||||
|
18
library/ui-styles/src/main/res/values/styles_tablayout.xml
Normal file
18
library/ui-styles/src/main/res/values/styles_tablayout.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Widget.Vector.TabLayout" parent="Widget.MaterialComponents.TabLayout">
|
||||
<item name="materialThemeOverlay">@style/ThemeOverlay.Vector.HomeFilterTabLayout</item>
|
||||
<item name="tabTextAppearance">@style/TextAppearance.Vector.FilterTabTextAppearance</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Vector.FilterTabTextAppearance" parent="TextAppearance.Vector.Subtitle">
|
||||
<item name="textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.Vector.HomeFilterTabLayout" parent="Theme.Vector.Launcher">
|
||||
<item name="colorSurface">?vctr_toolbar_background</item>
|
||||
<item name="colorOnSurface">?vctr_content_secondary</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -39,4 +39,14 @@
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
<!-- Material 3 -->
|
||||
|
||||
<style name="Widget.Vector.Material3.Toolbar" parent="Widget.Material3.Toolbar" />
|
||||
|
||||
<style name="Widget.Vector.Material3.CollapsingToolbar.Medium" parent="Widget.Material3.CollapsingToolbar.Medium">
|
||||
<item name="expandedTitleTextAppearance">@style/TextAppearance.Vector.Title.Medium</item>
|
||||
<item name="expandedTitleMarginBottom">20dp</item>
|
||||
<item name="collapsedTitleTextAppearance">@style/TextAppearance.Vector.Headline.Bold</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@@ -32,6 +32,15 @@
|
||||
<item name="android:textColor">?vctr_content_primary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Vector.Headline.Bold" parent="TextAppearance.MaterialComponents.Headline1">
|
||||
<item name="fontFamily">sans-serif</item>
|
||||
<item name="android:fontFamily">sans-serif</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:textSize">@dimen/text_size_headline</item>
|
||||
<item name="android:letterSpacing">0</item>
|
||||
<item name="android:textColor">?vctr_content_primary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Vector.Subtitle" parent="TextAppearance.MaterialComponents.Subtitle1">
|
||||
<item name="fontFamily">sans-serif</item>
|
||||
<item name="android:fontFamily">sans-serif</item>
|
||||
|
@@ -25,4 +25,4 @@
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
@@ -149,6 +149,9 @@
|
||||
|
||||
<!-- Location sharing -->
|
||||
<item name="vctr_live_location">@color/vctr_live_location_dark</item>
|
||||
|
||||
<!-- Material 3 -->
|
||||
<item name="collapsingToolbarLayoutMediumSize">@dimen/collapsing_toolbar_layout_medium_size</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Vector.Dark" parent="Base.Theme.Vector.Dark" />
|
||||
|
@@ -150,8 +150,12 @@
|
||||
|
||||
<!-- Location sharing -->
|
||||
<item name="vctr_live_location">@color/vctr_live_location_light</item>
|
||||
|
||||
<!-- Material 3 -->
|
||||
<item name="collapsingToolbarLayoutMediumSize">@dimen/collapsing_toolbar_layout_medium_size</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Vector.Light" parent="Base.Theme.Vector.Light" />
|
||||
|
||||
</resources>
|
||||
|
||||
|
@@ -17,7 +17,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "io.realm:realm-gradle-plugin:10.11.0"
|
||||
classpath "io.realm:realm-gradle-plugin:10.11.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.34\""
|
||||
|
||||
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
|
||||
|
@@ -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 &&
|
||||
|
@@ -29,14 +29,12 @@ data class RoomGuestAccessContent(
|
||||
// Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
|
||||
@Json(name = "guest_access") val guestAccessStr: String? = null
|
||||
) {
|
||||
val guestAccess: GuestAccess? = when (guestAccessStr) {
|
||||
"can_join" -> GuestAccess.CanJoin
|
||||
"forbidden" -> GuestAccess.Forbidden
|
||||
else -> {
|
||||
Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
|
||||
null
|
||||
}
|
||||
}
|
||||
val guestAccess: GuestAccess? = GuestAccess.values()
|
||||
.find { it.value == guestAccessStr }
|
||||
?: run {
|
||||
Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
|
@@ -23,30 +23,30 @@ import com.squareup.moshi.JsonClass
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#room-history-visibility
|
||||
*/
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class RoomHistoryVisibility {
|
||||
enum class RoomHistoryVisibility(val value: String) {
|
||||
/**
|
||||
* All events while this is the m.room.history_visibility value may be shared by any
|
||||
* participating homeserver with anyone, regardless of whether they have ever joined the room.
|
||||
*/
|
||||
@Json(name = "world_readable") WORLD_READABLE,
|
||||
@Json(name = "world_readable") WORLD_READABLE("world_readable"),
|
||||
|
||||
/**
|
||||
* Previous events are always accessible to newly joined members. All events in the
|
||||
* room are accessible, even those sent when the member was not a part of the room.
|
||||
*/
|
||||
@Json(name = "shared") SHARED,
|
||||
@Json(name = "shared") SHARED("shared"),
|
||||
|
||||
/**
|
||||
* Events are accessible to newly joined members from the point they were invited onwards.
|
||||
* Events stop being accessible when the member's state changes to something other than invite or join.
|
||||
*/
|
||||
@Json(name = "invited") INVITED,
|
||||
@Json(name = "invited") INVITED("invited"),
|
||||
|
||||
/**
|
||||
* Events are accessible to newly joined members from the point they joined the room onwards.
|
||||
* Events stop being accessible when the member's state changes to something other than join.
|
||||
*/
|
||||
@Json(name = "joined") JOINED
|
||||
@Json(name = "joined") JOINED("joined")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -24,14 +24,10 @@ import timber.log.Timber
|
||||
data class RoomHistoryVisibilityContent(
|
||||
@Json(name = "history_visibility") val historyVisibilityStr: String? = null
|
||||
) {
|
||||
val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) {
|
||||
"world_readable" -> RoomHistoryVisibility.WORLD_READABLE
|
||||
"shared" -> RoomHistoryVisibility.SHARED
|
||||
"invited" -> RoomHistoryVisibility.INVITED
|
||||
"joined" -> RoomHistoryVisibility.JOINED
|
||||
else -> {
|
||||
Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
|
||||
null
|
||||
}
|
||||
}
|
||||
val historyVisibility: RoomHistoryVisibility? = RoomHistoryVisibility.values()
|
||||
.find { it.value == historyVisibilityStr }
|
||||
?: run {
|
||||
Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.model.create
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||
@@ -30,7 +29,7 @@ interface RoomFeaturePreset {
|
||||
|
||||
fun updateRoomParams(params: CreateRoomParams)
|
||||
|
||||
fun setupInitialStates(): List<Event>?
|
||||
fun setupInitialStates(): List<CreateRoomStateEvent>?
|
||||
}
|
||||
|
||||
class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, val restrictedList: List<RoomJoinRulesAllowEntry>) : RoomFeaturePreset {
|
||||
@@ -41,9 +40,9 @@ class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, v
|
||||
params.roomVersion = homeServerCapabilities.versionOverrideForFeature(HomeServerCapabilities.ROOM_CAP_RESTRICTED)
|
||||
}
|
||||
|
||||
override fun setupInitialStates(): List<Event>? {
|
||||
override fun setupInitialStates(): List<CreateRoomStateEvent> {
|
||||
return listOf(
|
||||
Event(
|
||||
CreateRoomStateEvent(
|
||||
type = EventType.STATE_ROOM_JOIN_RULES,
|
||||
stateKey = "",
|
||||
content = RoomJoinRulesContent(
|
||||
|
@@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||
|
||||
/**
|
||||
* Content of the state event of type
|
||||
* Content of the event of type
|
||||
* [EventType.BEACON_LOCATION_DATA][org.matrix.android.sdk.api.session.events.model.EventType.BEACON_LOCATION_DATA]
|
||||
*
|
||||
* It contains location data related to a live location share.
|
||||
|
@@ -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 ->
|
||||
|
@@ -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
|
||||
|
@@ -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()}")
|
||||
|
@@ -76,12 +76,12 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||
Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
|
||||
callback.invoke(localId, validKeyReq)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
|
||||
Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,12 +103,12 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_READY, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||
Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
|
||||
callback?.invoke()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
|
||||
Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(type, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## SAS verification [$tx.transactionId] toDevice type '$type' success.")
|
||||
Timber.v("## SAS verification [${tx.transactionId}] toDevice type '$type' success.")
|
||||
if (onDone != null) {
|
||||
onDone()
|
||||
} else {
|
||||
@@ -149,7 +149,7 @@ internal class VerificationTransportToDevice(
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## SAS verification [$tx.transactionId] failed to send toDevice in state : $tx.state")
|
||||
Timber.e("## SAS verification [${tx.transactionId}] failed to send toDevice in state : ${tx.state}")
|
||||
tx.cancel(onErrorReason)
|
||||
}
|
||||
}
|
||||
|
@@ -93,7 +93,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
|
||||
return
|
||||
}
|
||||
|
||||
listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file ->
|
||||
listOf(REALM_NAME, "${REALM_NAME}.lock", "${REALM_NAME}.note", "${REALM_NAME}.management").forEach { file ->
|
||||
try {
|
||||
File(directory, file).deleteRecursively()
|
||||
} catch (e: Exception) {
|
||||
|
@@ -20,8 +20,13 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
|
||||
import org.matrix.android.sdk.api.session.identity.toMedium
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.util.MimeTypes
|
||||
import org.matrix.android.sdk.internal.crypto.DeviceListManager
|
||||
@@ -78,7 +83,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
buildAvatarEvent(params),
|
||||
buildGuestAccess(params)
|
||||
) +
|
||||
params.featurePreset?.setupInitialStates().orEmpty() +
|
||||
buildFeaturePresetInitialStates(params) +
|
||||
buildCustomInitialStates(params)
|
||||
)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
@@ -99,6 +104,16 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildFeaturePresetInitialStates(params: CreateRoomParams): List<Event> {
|
||||
return params.featurePreset?.setupInitialStates().orEmpty().map {
|
||||
Event(
|
||||
type = it.type,
|
||||
stateKey = it.stateKey,
|
||||
content = it.content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildCustomInitialStates(params: CreateRoomParams): List<Event> {
|
||||
return params.initialStates.map {
|
||||
Event(
|
||||
@@ -123,7 +138,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_AVATAR,
|
||||
stateKey = "",
|
||||
content = mapOf("url" to response.contentUri)
|
||||
content = RoomAvatarContent(response.contentUri).toContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -134,7 +149,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
stateKey = "",
|
||||
content = mapOf("history_visibility" to it)
|
||||
content = RoomHistoryVisibilityContent(it.value).toContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -145,7 +160,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_GUEST_ACCESS,
|
||||
stateKey = "",
|
||||
content = mapOf("guest_access" to it.value)
|
||||
content = RoomGuestAccessContent(it.value).toContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -167,7 +182,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_ENCRYPTION,
|
||||
stateKey = "",
|
||||
content = mapOf("algorithm" to it)
|
||||
content = EncryptionEventContent(it).toContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
}
|
||||
|
||||
|
@@ -16,21 +16,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#######################################################################################################################
|
||||
# Check frozen class modification
|
||||
#######################################################################################################################
|
||||
|
||||
echo "Check if frozen class modified"
|
||||
git diff "HEAD@{1}" --name-only | grep -e OlmInboundGroupSessionWrapper.kt -e OlmInboundGroupSessionWrapper2.kt
|
||||
FROZEN_CHANGED=$?
|
||||
if [ ${FROZEN_CHANGED} -eq 0 ]; then
|
||||
echo "❌ FROZEN CLASS CHANGED ERROR"
|
||||
exit 1
|
||||
else
|
||||
echo "Frozen check OK"
|
||||
fi
|
||||
|
||||
|
||||
#######################################################################################################################
|
||||
# Check drawable quantity
|
||||
#######################################################################################################################
|
||||
|
@@ -185,3 +185,6 @@ System\.currentTimeMillis\(\)===2
|
||||
onCreateOptionsMenu
|
||||
onOptionsItemSelected
|
||||
onPrepareOptionsMenu
|
||||
|
||||
### Suspicious String template. Please check that the string template will behave as expected, i.e. the class field and not the whole object will be used. For instance `Timber.d("$event.type")` is not correct, you should write `Timber.d("${event.type}")`. In the former the whole event content will be logged, since it's a data class. If this is expected (i.e. to fix false positive), please add explicit curly braces (`{` and `}`) around the variable, for instance `"elementLogs.${i}.txt"`
|
||||
\$[a-zA-Z_]\w*\??\.[a-zA-Z_]
|
||||
|
29
tools/danger/dangerfile-lint.js
Normal file
29
tools/danger/dangerfile-lint.js
Normal file
@@ -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?: ""
|
||||
}))
|
120
tools/danger/dangerfile.js
Normal file
120
tools/danger/dangerfile.js
Normal file
@@ -0,0 +1,120 @@
|
||||
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 that frozen classes have not been modified
|
||||
const frozenClasses = [
|
||||
"OlmInboundGroupSessionWrapper.kt",
|
||||
"OlmInboundGroupSessionWrapper2.kt",
|
||||
]
|
||||
|
||||
frozenClasses.forEach(frozen => {
|
||||
if (editedFiles.some(file => file.endsWith(frozen))) {
|
||||
fail("Frozen class `" + frozen + "` has been modified. Please do not modify frozen class.")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 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.")
|
||||
}
|
@@ -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:
|
||||
|
@@ -2634,7 +2634,8 @@
|
||||
"mask",
|
||||
"sick",
|
||||
"ill",
|
||||
"disease"
|
||||
"disease",
|
||||
"covid"
|
||||
]
|
||||
},
|
||||
"face-with-thermometer": {
|
||||
@@ -2647,7 +2648,8 @@
|
||||
"thermometer",
|
||||
"temperature",
|
||||
"cold",
|
||||
"fever"
|
||||
"fever",
|
||||
"covid"
|
||||
]
|
||||
},
|
||||
"face-with-headbandage": {
|
||||
@@ -4481,7 +4483,9 @@
|
||||
"hope",
|
||||
"wish",
|
||||
"namaste",
|
||||
"highfive"
|
||||
"highfive",
|
||||
"thank you",
|
||||
"appreciate"
|
||||
]
|
||||
},
|
||||
"writing-hand": {
|
||||
@@ -9581,7 +9585,8 @@
|
||||
"amoeba",
|
||||
"bacteria",
|
||||
"virus",
|
||||
"germs"
|
||||
"germs",
|
||||
"covid"
|
||||
]
|
||||
},
|
||||
"bouquet": {
|
||||
@@ -10260,7 +10265,9 @@
|
||||
"baguette",
|
||||
"bread",
|
||||
"food",
|
||||
"french"
|
||||
"french",
|
||||
"france",
|
||||
"bakery"
|
||||
]
|
||||
},
|
||||
"flatbread": {
|
||||
@@ -10272,7 +10279,8 @@
|
||||
"naan",
|
||||
"pita",
|
||||
"flour",
|
||||
"food"
|
||||
"food",
|
||||
"bakery"
|
||||
]
|
||||
},
|
||||
"pretzel": {
|
||||
@@ -10282,7 +10290,9 @@
|
||||
"twisted",
|
||||
"convoluted",
|
||||
"food",
|
||||
"bread"
|
||||
"bread",
|
||||
"germany",
|
||||
"bakery"
|
||||
]
|
||||
},
|
||||
"bagel": {
|
||||
@@ -10293,7 +10303,8 @@
|
||||
"breakfast",
|
||||
"schmear",
|
||||
"food",
|
||||
"bread"
|
||||
"bread",
|
||||
"jewish"
|
||||
]
|
||||
},
|
||||
"pancakes": {
|
||||
@@ -10306,7 +10317,8 @@
|
||||
"hotcake",
|
||||
"pancake",
|
||||
"flapjacks",
|
||||
"hotcakes"
|
||||
"hotcakes",
|
||||
"brunch"
|
||||
]
|
||||
},
|
||||
"waffle": {
|
||||
@@ -10316,7 +10328,8 @@
|
||||
"breakfast",
|
||||
"indecisive",
|
||||
"iron",
|
||||
"food"
|
||||
"food",
|
||||
"brunch"
|
||||
]
|
||||
},
|
||||
"cheese-wedge": {
|
||||
@@ -10325,7 +10338,8 @@
|
||||
"j": [
|
||||
"cheese",
|
||||
"food",
|
||||
"chadder"
|
||||
"chadder",
|
||||
"swiss"
|
||||
]
|
||||
},
|
||||
"meat-on-bone": {
|
||||
@@ -10376,7 +10390,8 @@
|
||||
"food",
|
||||
"meat",
|
||||
"pork",
|
||||
"pig"
|
||||
"pig",
|
||||
"brunch"
|
||||
]
|
||||
},
|
||||
"hamburger": {
|
||||
@@ -10400,7 +10415,8 @@
|
||||
"fries",
|
||||
"chips",
|
||||
"snack",
|
||||
"fast food"
|
||||
"fast food",
|
||||
"potato"
|
||||
]
|
||||
},
|
||||
"pizza": {
|
||||
@@ -10410,7 +10426,8 @@
|
||||
"cheese",
|
||||
"slice",
|
||||
"food",
|
||||
"party"
|
||||
"party",
|
||||
"italy"
|
||||
]
|
||||
},
|
||||
"hot-dog": {
|
||||
@@ -10420,7 +10437,8 @@
|
||||
"frankfurter",
|
||||
"hotdog",
|
||||
"sausage",
|
||||
"food"
|
||||
"food",
|
||||
"america"
|
||||
]
|
||||
},
|
||||
"sandwich": {
|
||||
@@ -10429,7 +10447,9 @@
|
||||
"j": [
|
||||
"bread",
|
||||
"food",
|
||||
"lunch"
|
||||
"lunch",
|
||||
"toast",
|
||||
"bakery"
|
||||
]
|
||||
},
|
||||
"taco": {
|
||||
@@ -10468,7 +10488,8 @@
|
||||
"food",
|
||||
"gyro",
|
||||
"kebab",
|
||||
"stuffed"
|
||||
"stuffed",
|
||||
"mediterranean"
|
||||
]
|
||||
},
|
||||
"falafel": {
|
||||
@@ -10477,7 +10498,8 @@
|
||||
"j": [
|
||||
"chickpea",
|
||||
"meatball",
|
||||
"food"
|
||||
"food",
|
||||
"mediterranean"
|
||||
]
|
||||
},
|
||||
"egg": {
|
||||
@@ -10498,7 +10520,8 @@
|
||||
"frying",
|
||||
"pan",
|
||||
"food",
|
||||
"kitchen"
|
||||
"kitchen",
|
||||
"skillet"
|
||||
]
|
||||
},
|
||||
"shallow-pan-of-food": {
|
||||
@@ -10510,7 +10533,8 @@
|
||||
"paella",
|
||||
"pan",
|
||||
"shallow",
|
||||
"cooking"
|
||||
"cooking",
|
||||
"skillet"
|
||||
]
|
||||
},
|
||||
"pot-of-food": {
|
||||
@@ -10521,7 +10545,8 @@
|
||||
"stew",
|
||||
"food",
|
||||
"meat",
|
||||
"soup"
|
||||
"soup",
|
||||
"hot pot"
|
||||
]
|
||||
},
|
||||
"fondue": {
|
||||
@@ -10556,7 +10581,8 @@
|
||||
"green",
|
||||
"salad",
|
||||
"healthy",
|
||||
"lettuce"
|
||||
"lettuce",
|
||||
"vegetable"
|
||||
]
|
||||
},
|
||||
"popcorn": {
|
||||
@@ -10566,7 +10592,8 @@
|
||||
"food",
|
||||
"movie theater",
|
||||
"films",
|
||||
"snack"
|
||||
"snack",
|
||||
"drama"
|
||||
]
|
||||
},
|
||||
"butter": {
|
||||
@@ -10592,7 +10619,8 @@
|
||||
"j": [
|
||||
"can",
|
||||
"food",
|
||||
"soup"
|
||||
"soup",
|
||||
"tomatoes"
|
||||
]
|
||||
},
|
||||
"bento-box": {
|
||||
@@ -10602,7 +10630,8 @@
|
||||
"bento",
|
||||
"box",
|
||||
"food",
|
||||
"japanese"
|
||||
"japanese",
|
||||
"lunch"
|
||||
]
|
||||
},
|
||||
"rice-cracker": {
|
||||
@@ -10612,7 +10641,8 @@
|
||||
"cracker",
|
||||
"rice",
|
||||
"food",
|
||||
"japanese"
|
||||
"japanese",
|
||||
"snack"
|
||||
]
|
||||
},
|
||||
"rice-ball": {
|
||||
@@ -10633,7 +10663,6 @@
|
||||
"cooked",
|
||||
"rice",
|
||||
"food",
|
||||
"china",
|
||||
"asian"
|
||||
]
|
||||
},
|
||||
@@ -10680,7 +10709,8 @@
|
||||
"roasted",
|
||||
"sweet",
|
||||
"food",
|
||||
"nature"
|
||||
"nature",
|
||||
"plant"
|
||||
]
|
||||
},
|
||||
"oden": {
|
||||
@@ -10745,7 +10775,8 @@
|
||||
"autumn",
|
||||
"festival",
|
||||
"yuèbǐng",
|
||||
"food"
|
||||
"food",
|
||||
"dessert"
|
||||
]
|
||||
},
|
||||
"dango": {
|
||||
@@ -10772,7 +10803,8 @@
|
||||
"jiaozi",
|
||||
"pierogi",
|
||||
"potsticker",
|
||||
"food"
|
||||
"food",
|
||||
"gyoza"
|
||||
]
|
||||
},
|
||||
"fortune-cookie": {
|
||||
@@ -10780,7 +10812,8 @@
|
||||
"b": "1F960",
|
||||
"j": [
|
||||
"prophecy",
|
||||
"food"
|
||||
"food",
|
||||
"dessert"
|
||||
]
|
||||
},
|
||||
"takeout-box": {
|
||||
@@ -22169,7 +22202,9 @@
|
||||
"nation",
|
||||
"country",
|
||||
"banner",
|
||||
"japan"
|
||||
"japan",
|
||||
"jp",
|
||||
"ja"
|
||||
]
|
||||
},
|
||||
"flag-kenya": {
|
||||
|
@@ -28,6 +28,7 @@ mv ./fastlane/metadata/android/fy ./fastlane_tmp
|
||||
mv ./fastlane/metadata/android/ga ./fastlane_tmp
|
||||
mv ./fastlane/metadata/android/kab ./fastlane_tmp
|
||||
mv ./fastlane/metadata/android/nb ./fastlane_tmp
|
||||
mv ./fastlane/metadata/android/gl ./fastlane_tmp
|
||||
|
||||
# Fastlane / PlayStore require longDescription and shortDescription file to be set, so copy the default
|
||||
# one for languages where they are missing
|
||||
|
@@ -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
|
@@ -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
|
||||
}
|
@@ -36,4 +36,57 @@ object Config {
|
||||
* - 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 = true
|
||||
|
||||
const val ENABLE_LOCATION_SHARING = true
|
||||
const val LOCATION_MAP_TILER_KEY = "fU3vlMsMn4Jb6dnEIFsx"
|
||||
|
||||
/**
|
||||
* 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.FTUE_AUTH
|
||||
|
||||
/**
|
||||
* 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.PostHog(
|
||||
postHogHost = "https://posthog.element.dev",
|
||||
postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN",
|
||||
policyLink = "https://element.io/cookie-policy",
|
||||
)
|
||||
|
||||
/**
|
||||
* The analytics configuration to use for the Release build type.
|
||||
* Can be disabled by providing Analytics.Disabled
|
||||
*/
|
||||
val RELEASE_ANALYTICS_CONFIG = Analytics.PostHog(
|
||||
postHogHost = "https://posthog.hss.element.io",
|
||||
postHogApiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
|
||||
policyLink = "https://element.io/cookie-policy",
|
||||
)
|
||||
|
||||
/**
|
||||
* The analytics configuration to use for the Nightly build type.
|
||||
* Can be disabled by providing Analytics.Disabled
|
||||
*/
|
||||
val NIGHTLY_ANALYTICS_CONFIG = RELEASE_ANALYTICS_CONFIG
|
||||
}
|
||||
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 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,
|
||||
|
||||
/**
|
||||
* Keys will be sent for the first time when the timeline displayed.
|
||||
*/
|
||||
WhenEnteringRoom,
|
||||
|
||||
/**
|
||||
* Keys will be sent for the first time when a typing started.
|
||||
*/
|
||||
WhenTyping
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
@@ -14,14 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.login2
|
||||
package im.vector.app.config
|
||||
|
||||
enum class SignMode2 {
|
||||
Unknown,
|
||||
|
||||
// Account creation
|
||||
SignUp,
|
||||
|
||||
// Login
|
||||
SignIn
|
||||
enum class OnboardingVariant {
|
||||
LEGACY,
|
||||
FTUE_AUTH
|
||||
}
|
@@ -27,6 +27,7 @@ knit {
|
||||
exclude '**/.gradle/**'
|
||||
exclude '**/towncrier/template.md'
|
||||
exclude '**/CHANGES.md'
|
||||
exclude '/node_modules'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ ext.versionMinor = 4
|
||||
// Note: even values are reserved for regular release, odd values for hotfix release.
|
||||
// When creating a hotfix, you should decrease the value, since the current value
|
||||
// is the value for the next regular release.
|
||||
ext.versionPatch = 30
|
||||
ext.versionPatch = 34
|
||||
|
||||
static def getGitTimestamp() {
|
||||
def cmd = 'git show -s --format=%ct'
|
||||
@@ -155,19 +156,6 @@ 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.FTUE_AUTH"
|
||||
|
||||
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"
|
||||
|
||||
buildConfigField "Boolean", "enableLocationSharing", "true"
|
||||
buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\""
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// Keep abiFilter for the universalApk
|
||||
@@ -249,10 +237,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"
|
||||
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
if (project.hasProperty("coverage")) {
|
||||
@@ -264,10 +248,6 @@ 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"
|
||||
|
||||
// When updating this block, please also update the same block in the `nightly` buildType below
|
||||
postprocessing {
|
||||
removeUnusedCode true
|
||||
removeUnusedResources true
|
||||
@@ -327,8 +307,6 @@ android {
|
||||
isDefault = true
|
||||
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getGplayVersionSuffix()}"
|
||||
|
||||
resValue "bool", "isGplay", "true"
|
||||
buildConfigField "boolean", "ALLOW_FCM_USE", "true"
|
||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
|
||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
|
||||
}
|
||||
@@ -338,8 +316,6 @@ android {
|
||||
|
||||
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getFdroidVersionSuffix()}"
|
||||
|
||||
resValue "bool", "isGplay", "false"
|
||||
buildConfigField "boolean", "ALLOW_FCM_USE", "false"
|
||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
|
||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
|
||||
}
|
||||
@@ -415,7 +391,7 @@ dependencies {
|
||||
implementation libs.androidx.biometric
|
||||
|
||||
implementation "org.threeten:threetenbp:1.4.0:no-tzdb"
|
||||
implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.10.0"
|
||||
implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.11.0"
|
||||
|
||||
implementation libs.squareup.moshi
|
||||
kapt libs.squareup.moshiKotlin
|
||||
@@ -437,7 +413,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
|
||||
@@ -449,6 +425,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
|
||||
@@ -521,7 +500,7 @@ dependencies {
|
||||
implementation 'com.posthog.android:posthog:1.1.2'
|
||||
|
||||
// UnifiedPush
|
||||
implementation 'com.github.UnifiedPush:android-connector:2.0.0'
|
||||
implementation 'com.github.UnifiedPush:android-connector:2.0.1'
|
||||
// UnifiedPush gplay flavor only
|
||||
gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:2.1.1') {
|
||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||
@@ -597,7 +576,7 @@ dependencies {
|
||||
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'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
|
||||
|
||||
androidTestImplementation libs.androidx.testCore
|
||||
androidTestImplementation libs.androidx.testRunner
|
||||
@@ -620,4 +599,5 @@ dependencies {
|
||||
androidTestImplementation libs.mockk.mockkAndroid
|
||||
androidTestUtil libs.androidx.orchestrator
|
||||
debugImplementation libs.androidx.fragmentTesting
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10"
|
||||
}
|
||||
|
@@ -102,6 +102,7 @@
|
||||
<!-- Wording -->
|
||||
<issue id="Typos" severity="error" />
|
||||
<issue id="TypographyDashes" severity="error" />
|
||||
<issue id="PluralsCandidate" severity="error" />
|
||||
|
||||
<!-- DI -->
|
||||
<issue id="JvmStaticProvidesInObjectDetector" severity="error" />
|
||||
|
@@ -27,6 +27,7 @@ import im.vector.app.features.MainActivity
|
||||
import im.vector.app.ui.robot.ElementRobot
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.UUID
|
||||
|
||||
@@ -35,7 +36,9 @@ import java.util.UUID
|
||||
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()}"
|
||||
|
@@ -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<Preferences> {
|
||||
val klass = AnalyticsStore::class.asTopLevel()
|
||||
val method = klass.getMethod("access\$getDataStore", Context::class.java)
|
||||
return method.invoke(klass, context) as DataStore<Preferences>
|
||||
}
|
@@ -83,7 +83,7 @@ private fun useMediaStoreScreenshotStorage(
|
||||
screenshotLocation: String,
|
||||
bitmap: Bitmap
|
||||
) {
|
||||
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$screenshotName.jpeg")
|
||||
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "${screenshotName}.jpeg")
|
||||
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, screenshotLocation)
|
||||
val uri: Uri? = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||
if (uri != null) {
|
||||
@@ -104,7 +104,7 @@ private fun usePublicExternalScreenshotStorage(
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
val file = File(directory, "$screenshotName.jpeg")
|
||||
val file = File(directory, "${screenshotName}.jpeg")
|
||||
saveScreenshotToStream(bitmap, FileOutputStream(file))
|
||||
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||
}
|
||||
|
@@ -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<Boolean>(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<LockScreenTestActivity>(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(
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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) }
|
||||
|
@@ -76,7 +76,7 @@ class EmojiDataSourceTest : InstrumentedTest {
|
||||
fun searchTestOneResult() {
|
||||
val emojiDataSource = createEmojiDataSource()
|
||||
val result = runBlocking {
|
||||
emojiDataSource.filterWith("france")
|
||||
emojiDataSource.filterWith("flag-france")
|
||||
}
|
||||
assertEquals("Should have 1 result", 1, result.size)
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@
|
||||
<activity android:name=".features.debug.settings.DebugPrivateSettingsActivity" />
|
||||
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
|
||||
<activity android:name=".features.debug.features.DebugFeaturesSettingsActivity" />
|
||||
<activity android:name=".features.debug.DebugMenuActivity" />
|
||||
<activity android:name=".features.debug.leak.DebugMemoryLeaksActivity" />
|
||||
|
||||
<activity
|
||||
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
|
||||
|
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.config
|
||||
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.features.analytics.AnalyticsConfig
|
||||
|
||||
val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig {
|
||||
override val isEnabled = BuildConfig.APPLICATION_ID == "im.vector.app.debug"
|
||||
override val postHogHost = "https://posthog.element.dev"
|
||||
override val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN"
|
||||
override val policyLink = "https://element.io/cookie-policy"
|
||||
}
|
@@ -37,6 +37,7 @@ import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.ActivityDebugMenuBinding
|
||||
import im.vector.app.features.debug.analytics.DebugAnalyticsActivity
|
||||
import im.vector.app.features.debug.features.DebugFeaturesSettingsActivity
|
||||
import im.vector.app.features.debug.leak.DebugMemoryLeaksActivity
|
||||
import im.vector.app.features.debug.sas.DebugSasEmojiActivity
|
||||
import im.vector.app.features.debug.settings.DebugPrivateSettingsActivity
|
||||
import im.vector.app.features.qrcode.QrCodeScannerActivity
|
||||
@@ -86,6 +87,7 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
|
||||
views.debugAnalytics.setOnClickListener {
|
||||
startActivity(Intent(this, DebugAnalyticsActivity::class.java))
|
||||
}
|
||||
views.debugMemoryLeaks.setOnClickListener { openMemoryLeaksSettings() }
|
||||
views.debugTestTextViewLink.setOnClickListener { testTextViewLink() }
|
||||
views.debugOpenButtonStylesLight.setOnClickListener {
|
||||
startActivity(Intent(this, DebugVectorButtonStylesLightActivity::class.java))
|
||||
@@ -130,6 +132,10 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
|
||||
startActivity(Intent(this, DebugPrivateSettingsActivity::class.java))
|
||||
}
|
||||
|
||||
private fun openMemoryLeaksSettings() {
|
||||
startActivity(Intent(this, DebugMemoryLeaksActivity::class.java))
|
||||
}
|
||||
|
||||
private fun renderQrCode(text: String) {
|
||||
views.debugQrCode.setData(text)
|
||||
}
|
||||
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.debug.di
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import im.vector.app.core.debug.DebugNavigator
|
||||
import im.vector.app.core.debug.DebugReceiver
|
||||
import im.vector.app.core.debug.FlipperProxy
|
||||
import im.vector.app.core.debug.LeakDetector
|
||||
import im.vector.app.features.debug.DebugMenuActivity
|
||||
import im.vector.app.flipper.VectorFlipperProxy
|
||||
import im.vector.app.leakcanary.LeakCanaryLeakDetector
|
||||
import im.vector.app.receivers.VectorDebugReceiver
|
||||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
abstract class DebugModule {
|
||||
|
||||
companion object {
|
||||
|
||||
@Provides
|
||||
fun providesDebugNavigator() = object : DebugNavigator {
|
||||
override fun openDebugMenu(context: Context) {
|
||||
context.startActivity(Intent(context, DebugMenuActivity::class.java))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract fun bindsDebugReceiver(receiver: VectorDebugReceiver): DebugReceiver
|
||||
|
||||
@Binds
|
||||
abstract fun bindsFlipperProxy(flipperProxy: VectorFlipperProxy): FlipperProxy
|
||||
|
||||
@Binds
|
||||
abstract fun bindsLeakDetector(leakDetector: LeakCanaryLeakDetector): LeakDetector
|
||||
}
|
@@ -24,6 +24,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.MavericksViewModelComponent
|
||||
import im.vector.app.core.di.MavericksViewModelKey
|
||||
import im.vector.app.features.debug.analytics.DebugAnalyticsViewModel
|
||||
import im.vector.app.features.debug.leak.DebugMemoryLeaksViewModel
|
||||
import im.vector.app.features.debug.settings.DebugPrivateSettingsViewModel
|
||||
|
||||
@InstallIn(MavericksViewModelComponent::class)
|
||||
@@ -39,4 +40,9 @@ interface MavericksViewModelDebugModule {
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(DebugPrivateSettingsViewModel::class)
|
||||
fun debugPrivateSettingsViewModelFactory(factory: DebugPrivateSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(DebugMemoryLeaksViewModel::class)
|
||||
fun debugMemoryLeaksViewModelFactory(factory: DebugMemoryLeaksViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
}
|
||||
|
@@ -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,
|
||||
@@ -85,6 +90,11 @@ class DebugFeaturesStateFactory @Inject constructor(
|
||||
key = DebugFeatureKeys.newAppLayoutEnabled,
|
||||
factory = VectorFeatures::isNewAppLayoutEnabled
|
||||
),
|
||||
createBooleanFeature(
|
||||
label = "Enable New Device Management",
|
||||
key = DebugFeatureKeys.newDeviceManagementEnabled,
|
||||
factory = VectorFeatures::isNewDeviceManagementEnabled
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@@ -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>() ?: vectorFeatures.onboardingVariant()
|
||||
override fun onboardingVariant(): OnboardingVariant {
|
||||
return readPreferences().getEnum<OnboardingVariant>() ?: 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()
|
||||
|
||||
@@ -75,6 +79,9 @@ class DebugVectorFeatures(
|
||||
override fun isNewAppLayoutEnabled(): Boolean = read(DebugFeatureKeys.newAppLayoutEnabled)
|
||||
?: vectorFeatures.isNewAppLayoutEnabled()
|
||||
|
||||
override fun isNewDeviceManagementEnabled(): Boolean = read(DebugFeatureKeys.newDeviceManagementEnabled)
|
||||
?: vectorFeatures.isNewDeviceManagementEnabled()
|
||||
|
||||
fun <T> override(value: T?, key: Preferences.Key<T>) = updatePreferences {
|
||||
if (value == null) {
|
||||
it.remove(key)
|
||||
@@ -135,4 +142,5 @@ object DebugFeatureKeys {
|
||||
val forceUsageOfOpusEncoder = booleanPreferencesKey("force-usage-of-opus-encoder")
|
||||
val startDmOnFirstMsg = booleanPreferencesKey("start-dm-on-first-msg")
|
||||
val newAppLayoutEnabled = booleanPreferencesKey("new-app-layout-enabled")
|
||||
val newDeviceManagementEnabled = booleanPreferencesKey("new-device-management-enabled")
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.features.debug.leak
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleBinding
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DebugMemoryLeaksActivity : VectorBaseActivity<ActivitySimpleBinding>() {
|
||||
|
||||
override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater)
|
||||
|
||||
override fun initUiAndData() {
|
||||
if (isFirstCreation()) {
|
||||
addFragment(
|
||||
views.simpleFragmentContainer,
|
||||
DebugMemoryLeaksFragment::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.features.debug.leak
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentDebugMemoryLeaksBinding
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DebugMemoryLeaksFragment : VectorBaseFragment<FragmentDebugMemoryLeaksBinding>() {
|
||||
|
||||
private val viewModel: DebugMemoryLeaksViewModel by fragmentViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentDebugMemoryLeaksBinding {
|
||||
return FragmentDebugMemoryLeaksBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setViewListeners()
|
||||
}
|
||||
|
||||
private fun setViewListeners() {
|
||||
views.enableMemoryLeakAnalysis.onClick {
|
||||
viewModel.handle(DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis(views.enableMemoryLeakAnalysis.isChecked))
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { viewState ->
|
||||
views.enableMemoryLeakAnalysis.isChecked = viewState.isMemoryLeaksAnalysisEnabled
|
||||
}
|
||||
}
|
@@ -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.features.debug.leak
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed interface DebugMemoryLeaksViewActions : VectorViewModelAction {
|
||||
data class EnableMemoryLeaksAnalysis(val isEnabled: Boolean) : DebugMemoryLeaksViewActions
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.debug.leak
|
||||
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.debug.LeakDetector
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class DebugMemoryLeaksViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: DebugMemoryLeaksViewState,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val leakDetector: LeakDetector,
|
||||
) : VectorViewModel<DebugMemoryLeaksViewState, DebugMemoryLeaksViewActions, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<DebugMemoryLeaksViewModel, DebugMemoryLeaksViewState> {
|
||||
override fun create(initialState: DebugMemoryLeaksViewState): DebugMemoryLeaksViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<DebugMemoryLeaksViewModel, DebugMemoryLeaksViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
refreshStateFromPreferences()
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: DebugMemoryLeaksViewActions) {
|
||||
when (action) {
|
||||
is DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis -> handleEnableMemoryLeaksAnalysis(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEnableMemoryLeaksAnalysis(action: DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis) {
|
||||
viewModelScope.launch {
|
||||
vectorPreferences.enableMemoryLeakAnalysis(action.isEnabled)
|
||||
leakDetector.enable(action.isEnabled)
|
||||
refreshStateFromPreferences()
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshStateFromPreferences() {
|
||||
setState { copy(isMemoryLeaksAnalysisEnabled = vectorPreferences.isMemoryLeakAnalysisEnabled()) }
|
||||
}
|
||||
}
|
@@ -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.features.debug.leak
|
||||
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
|
||||
data class DebugMemoryLeaksViewState(
|
||||
val isMemoryLeaksAnalysisEnabled: Boolean = false
|
||||
) : MavericksState
|
@@ -29,19 +29,19 @@ import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPl
|
||||
import com.facebook.soloader.SoLoader
|
||||
import com.kgurgul.flipper.RealmDatabaseDriver
|
||||
import com.kgurgul.flipper.RealmDatabaseProvider
|
||||
import im.vector.app.core.debug.FlipperProxy
|
||||
import io.realm.RealmConfiguration
|
||||
import okhttp3.Interceptor
|
||||
import org.matrix.android.sdk.api.Matrix
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class FlipperProxy @Inject constructor(
|
||||
class VectorFlipperProxy @Inject constructor(
|
||||
private val context: Context,
|
||||
) {
|
||||
) : FlipperProxy {
|
||||
private val networkFlipperPlugin = NetworkFlipperPlugin()
|
||||
|
||||
fun init(matrix: Matrix) {
|
||||
override fun init(matrix: Matrix) {
|
||||
SoLoader.init(context, false)
|
||||
|
||||
if (FlipperUtils.shouldEnableFlipper(context)) {
|
||||
@@ -65,8 +65,5 @@ class FlipperProxy @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("RedundantNullableReturnType")
|
||||
fun getNetworkInterceptor(): Interceptor? {
|
||||
return FlipperOkhttpInterceptor(networkFlipperPlugin)
|
||||
}
|
||||
override fun networkInterceptor() = FlipperOkhttpInterceptor(networkFlipperPlugin)
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.leakcanary
|
||||
|
||||
import im.vector.app.core.debug.LeakDetector
|
||||
import leakcanary.LeakCanary
|
||||
import javax.inject.Inject
|
||||
|
||||
class LeakCanaryLeakDetector @Inject constructor() : LeakDetector {
|
||||
override fun enable(enable: Boolean) {
|
||||
LeakCanary.config = LeakCanary.config.copy(dumpHeap = enable)
|
||||
}
|
||||
}
|
@@ -22,14 +22,24 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import im.vector.app.core.debug.DebugReceiver
|
||||
import im.vector.app.core.di.DefaultSharedPreferences
|
||||
import im.vector.app.core.utils.lsFiles
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Receiver to handle some command from ADB
|
||||
*/
|
||||
class DebugReceiver : BroadcastReceiver() {
|
||||
class VectorDebugReceiver @Inject constructor() : BroadcastReceiver(), DebugReceiver {
|
||||
|
||||
override fun register(context: Context) {
|
||||
context.registerReceiver(this, getIntentFilter(context))
|
||||
}
|
||||
|
||||
override fun unregister(context: Context) {
|
||||
context.unregisterReceiver(this)
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Timber.v("Received debug action: ${intent.action}")
|
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
@@ -8,8 +9,11 @@
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_anchor="@+id/scrollView2"
|
||||
app:layout_anchorGravity="center">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -38,6 +42,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Analytics" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/debug_memory_leaks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Memory leaks" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/debug_test_text_view_link"
|
||||
android:layout_width="wrap_content"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user