mirror of
https://github.com/element-hq/element-android
synced 2024-11-25 02:45:37 +03:00
Merge branch 'release/v1.4.22'
This commit is contained in:
commit
3390e206b0
1108 changed files with 11082 additions and 8490 deletions
|
@ -764,7 +764,7 @@ ij_groovy_while_on_new_line = false
|
||||||
ij_groovy_wrap_long_lines = false
|
ij_groovy_wrap_long_lines = false
|
||||||
|
|
||||||
[{*.gradle.kts,*.kt,*.kts,*.main.kts}]
|
[{*.gradle.kts,*.kt,*.kts,*.main.kts}]
|
||||||
ij_kotlin_align_in_columns_case_branch = true
|
ij_kotlin_align_in_columns_case_branch = false
|
||||||
ij_kotlin_align_multiline_binary_operation = false
|
ij_kotlin_align_multiline_binary_operation = false
|
||||||
ij_kotlin_align_multiline_extends_list = false
|
ij_kotlin_align_multiline_extends_list = false
|
||||||
ij_kotlin_align_multiline_method_parentheses = false
|
ij_kotlin_align_multiline_method_parentheses = false
|
||||||
|
@ -810,8 +810,8 @@ ij_kotlin_line_comment_add_space = false
|
||||||
ij_kotlin_line_comment_at_first_column = true
|
ij_kotlin_line_comment_at_first_column = true
|
||||||
ij_kotlin_method_annotation_wrap = split_into_lines
|
ij_kotlin_method_annotation_wrap = split_into_lines
|
||||||
ij_kotlin_method_call_chain_wrap = off
|
ij_kotlin_method_call_chain_wrap = off
|
||||||
ij_kotlin_method_parameters_new_line_after_left_paren = false
|
ij_kotlin_method_parameters_new_line_after_left_paren = true
|
||||||
ij_kotlin_method_parameters_right_paren_on_new_line = false
|
ij_kotlin_method_parameters_right_paren_on_new_line = true
|
||||||
ij_kotlin_method_parameters_wrap = off
|
ij_kotlin_method_parameters_wrap = off
|
||||||
ij_kotlin_name_count_to_use_star_import = 2147483647
|
ij_kotlin_name_count_to_use_star_import = 2147483647
|
||||||
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
|
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
|
||||||
|
|
11
.github/ISSUE_TEMPLATE/bug.yml
vendored
11
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -73,3 +73,14 @@ body:
|
||||||
- 'No'
|
- 'No'
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: pr
|
||||||
|
attributes:
|
||||||
|
label: Are you willing to provide a PR?
|
||||||
|
description: |
|
||||||
|
Providing a PR can drastically speed up the process of fixing this bug. Don't worry, it's still OK to answer 'No' :).
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
11
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
11
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
|
@ -34,3 +34,14 @@ body:
|
||||||
placeholder: Is there anything else you'd like to add?
|
placeholder: Is there anything else you'd like to add?
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
id: pr
|
||||||
|
attributes:
|
||||||
|
label: Are you willing to provide a PR?
|
||||||
|
description: |
|
||||||
|
Don't worry, it's still OK to answer 'No' :).
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
26
.github/ISSUE_TEMPLATE/release.yml
vendored
26
.github/ISSUE_TEMPLATE/release.yml
vendored
|
@ -49,24 +49,34 @@ body:
|
||||||
|
|
||||||
### Once tested and validated internally
|
### Once tested and validated internally
|
||||||
|
|
||||||
- [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
|
- [ ] Create a new open testing release on the GooglePlay console and upload the 4 signed Apks.
|
||||||
- [ ] Check that the version codes are correct
|
- [ ] Check that the version codes are correct
|
||||||
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
|
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
|
||||||
- [ ] Push to beta release to 100% of the users
|
- [ ] Push the open testing release to 100% of the users
|
||||||
- [ ] Notify the F-Droid team so that they can schedule the publication on F-Droid
|
- [ ] Notify the F-Droid team [here](https://matrix.to/#/!LAAuJLQXYHjMNWKrCK:matrix.org?via=matrix.org&via=bubu1.eu&via=lant.uk) so that they can schedule the publication on F-Droid
|
||||||
|
- [ ] The application is available to the PlayStore testers (live). Google can take between 1 hour and up to 7 days to approve the release.
|
||||||
|
- [ ] The application is available to the F-Droid users.
|
||||||
|
|
||||||
### Once Live on PlayStore
|
### Once open testing is live on PlayStore
|
||||||
|
|
||||||
- [ ] Ping the Android public room and update its topic
|
- [ ] Ping the Android public room and update its topic
|
||||||
- [ ] Add an entry in the internal diary
|
|
||||||
|
|
||||||
### After at least 2 days
|
### Once Live on F-Droid
|
||||||
|
|
||||||
|
- [ ] Update the Android public room topic
|
||||||
|
|
||||||
|
### After at least 2 days (generally next Monday)
|
||||||
|
|
||||||
- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
|
- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
|
||||||
- [ ] Check the crash reports on the GooglePlay console
|
- [ ] Check the crash reports on the GooglePlay console
|
||||||
- [ ] Check the Android Element room for any reported issues on the new version
|
- [ ] Check the Android Element room for any reported issues on the new version
|
||||||
- [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
|
- [ ] If all is OK, promote the open testing release to production. Generally using a 100% roll out, but can be a smaller value depending on the release content.
|
||||||
- [ ] Ping the Android public room and update its topic with the new available version
|
- [ ] The application is available to the PlayStore users (live). Google can take (again!) between 1 hour and up to 7 days to approve the release.
|
||||||
|
|
||||||
|
### Once production is live on PlayStore
|
||||||
|
|
||||||
|
- [ ] Ping the Android public room and update its topic
|
||||||
|
- [ ] Add an entry in the internal diary
|
||||||
|
|
||||||
### Android SDK2
|
### Android SDK2
|
||||||
|
|
||||||
|
|
223
.github/workflows/post-pr.yml
vendored
223
.github/workflows/post-pr.yml
vendored
|
@ -29,200 +29,6 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Run those tests!" # no-op success
|
- run: echo "Run those tests!" # no-op success
|
||||||
|
|
||||||
# Run Android Tests
|
|
||||||
integration-tests:
|
|
||||||
name: Matrix SDK - Running Integration Tests
|
|
||||||
needs: should-i-run
|
|
||||||
runs-on: macos-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
api-level: [ 28 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'adopt'
|
|
||||||
java-version: 11
|
|
||||||
- name: Set up Python 3.8
|
|
||||||
uses: actions/setup-python@v3
|
|
||||||
with:
|
|
||||||
python-version: 3.8
|
|
||||||
- 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: Start synapse server
|
|
||||||
uses: michaelkaye/setup-matrix-synapse@v1.0.3
|
|
||||||
with:
|
|
||||||
uploadLogs: true
|
|
||||||
httpPort: 8080
|
|
||||||
disableRateLimiting: true
|
|
||||||
public_baseurl: "http://10.0.2.2:8080/"
|
|
||||||
# package: org.matrix.android.sdk.session
|
|
||||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.session] API[${{ matrix.api-level }}]
|
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
|
||||||
with:
|
|
||||||
api-level: ${{ matrix.api-level }}
|
|
||||||
arch: x86
|
|
||||||
profile: Nexus 5X
|
|
||||||
force-avd-creation: false
|
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
||||||
emulator-build: 7425822
|
|
||||||
script: |
|
|
||||||
adb root
|
|
||||||
adb logcat -c
|
|
||||||
touch emulator-session.log
|
|
||||||
chmod 777 emulator-session.log
|
|
||||||
adb logcat >> emulator-session.log &
|
|
||||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.session' matrix-sdk-android:connectedDebugAndroidTest
|
|
||||||
- name: Read Results [org.matrix.android.sdk.session]
|
|
||||||
if: always()
|
|
||||||
id: get-comment-body-session
|
|
||||||
run: python3 ./tools/ci/render_test_output.py session ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
|
||||||
- name: Remove adb logcat
|
|
||||||
if: always()
|
|
||||||
run: pkill -9 adb
|
|
||||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.account] API[${{ matrix.api-level }}]
|
|
||||||
if: always()
|
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
|
||||||
with:
|
|
||||||
api-level: ${{ matrix.api-level }}
|
|
||||||
arch: x86
|
|
||||||
profile: Nexus 5X
|
|
||||||
force-avd-creation: false
|
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
||||||
emulator-build: 7425822
|
|
||||||
script: |
|
|
||||||
adb root
|
|
||||||
adb logcat -c
|
|
||||||
touch emulator-account.log
|
|
||||||
chmod 777 emulator-account.log
|
|
||||||
adb logcat >> emulator-account.log &
|
|
||||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.account' matrix-sdk-android:connectedDebugAndroidTest
|
|
||||||
- name: Read Results [org.matrix.android.sdk.account]
|
|
||||||
if: always()
|
|
||||||
id: get-comment-body-account
|
|
||||||
run: python3 ./tools/ci/render_test_output.py account ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
|
||||||
- name: Remove adb logcat
|
|
||||||
if: always()
|
|
||||||
run: pkill -9 adb
|
|
||||||
# package: org.matrix.android.sdk.internal
|
|
||||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.internal] API[${{ matrix.api-level }}]
|
|
||||||
if: always()
|
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
|
||||||
with:
|
|
||||||
api-level: ${{ matrix.api-level }}
|
|
||||||
arch: x86
|
|
||||||
profile: Nexus 5X
|
|
||||||
force-avd-creation: false
|
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
||||||
emulator-build: 7425822
|
|
||||||
script: |
|
|
||||||
adb root
|
|
||||||
adb logcat -c
|
|
||||||
touch emulator-internal.log
|
|
||||||
chmod 777 emulator-internal.log
|
|
||||||
adb logcat >> emulator-internal.log &
|
|
||||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.internal' matrix-sdk-android:connectedDebugAndroidTest
|
|
||||||
- name: Read Results [org.matrix.android.sdk.internal]
|
|
||||||
if: always()
|
|
||||||
id: get-comment-body-internal
|
|
||||||
run: python3 ./tools/ci/render_test_output.py internal ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
|
||||||
- name: Remove adb logcat
|
|
||||||
if: always()
|
|
||||||
run: pkill -9 adb
|
|
||||||
# package: org.matrix.android.sdk.ordering
|
|
||||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.ordering] API[${{ matrix.api-level }}]
|
|
||||||
if: always()
|
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
|
||||||
with:
|
|
||||||
api-level: ${{ matrix.api-level }}
|
|
||||||
arch: x86
|
|
||||||
profile: Nexus 5X
|
|
||||||
force-avd-creation: false
|
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
||||||
emulator-build: 7425822
|
|
||||||
script: |
|
|
||||||
adb root
|
|
||||||
adb logcat -c
|
|
||||||
touch emulator-ordering.log
|
|
||||||
chmod 777 emulator-ordering.log
|
|
||||||
adb logcat >> emulator-ordering.log &
|
|
||||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.ordering' matrix-sdk-android:connectedDebugAndroidTest
|
|
||||||
- name: Read Results [org.matrix.android.sdk.ordering]
|
|
||||||
if: always()
|
|
||||||
id: get-comment-body-ordering
|
|
||||||
run: python3 ./tools/ci/render_test_output.py ordering ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
|
||||||
- name: Remove adb logcat
|
|
||||||
if: always()
|
|
||||||
run: pkill -9 adb
|
|
||||||
# package: class PermalinkParserTest
|
|
||||||
- name: Run integration tests for Matrix SDK class [org.matrix.android.sdk.PermalinkParserTest] API[${{ matrix.api-level }}]
|
|
||||||
if: always()
|
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
|
||||||
with:
|
|
||||||
api-level: ${{ matrix.api-level }}
|
|
||||||
arch: x86
|
|
||||||
profile: Nexus 5X
|
|
||||||
force-avd-creation: false
|
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
||||||
emulator-build: 7425822
|
|
||||||
script: |
|
|
||||||
adb root
|
|
||||||
adb logcat -c
|
|
||||||
touch emulator-permalink.log
|
|
||||||
chmod 777 emulator-permalink.log
|
|
||||||
adb logcat >> emulator-permalink.log &
|
|
||||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.class='org.matrix.android.sdk.PermalinkParserTest' matrix-sdk-android:connectedDebugAndroidTest
|
|
||||||
- name: Read Results [org.matrix.android.sdk.PermalinkParserTest]
|
|
||||||
if: always()
|
|
||||||
id: get-comment-body-permalink
|
|
||||||
run: python3 ./tools/ci/render_test_output.py permalink ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
|
||||||
- name: Remove adb logcat
|
|
||||||
if: always()
|
|
||||||
run: pkill -9 adb
|
|
||||||
# package: class PermalinkParserTest
|
|
||||||
- name: Find Comment
|
|
||||||
if: always() && github.event_name == 'pull_request'
|
|
||||||
uses: peter-evans/find-comment@v2
|
|
||||||
id: fc
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
comment-author: 'github-actions[bot]'
|
|
||||||
body-includes: Integration Tests Results
|
|
||||||
- name: Publish results to PR
|
|
||||||
if: always() && github.event_name == 'pull_request'
|
|
||||||
uses: peter-evans/create-or-update-comment@v2
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body: |
|
|
||||||
### Matrix SDK
|
|
||||||
## Integration Tests Results:
|
|
||||||
- `[org.matrix.android.sdk.session]`<br>${{ steps.get-comment-body-session.outputs.session }}
|
|
||||||
- `[org.matrix.android.sdk.account]`<br>${{ steps.get-comment-body-account.outputs.account }}
|
|
||||||
- `[org.matrix.android.sdk.internal]`<br>${{ steps.get-comment-body-internal.outputs.internal }}
|
|
||||||
- `[org.matrix.android.sdk.ordering]`<br>${{ steps.get-comment-body-ordering.outputs.ordering }}
|
|
||||||
- `[org.matrix.android.sdk.PermalinkParserTest]`<br>${{ steps.get-comment-body-permalink.outputs.permalink }}
|
|
||||||
edit-mode: replace
|
|
||||||
- name: Upload Test Report Log
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: integrationtest-error-results
|
|
||||||
path: |
|
|
||||||
emulator-permalink.log
|
|
||||||
emulator-internal.log
|
|
||||||
emulator-ordering.log
|
|
||||||
emulator-account.log
|
|
||||||
emulator-session.log
|
|
||||||
|
|
||||||
ui-tests:
|
ui-tests:
|
||||||
name: UI Tests (Synapse)
|
name: UI Tests (Synapse)
|
||||||
needs: should-i-run
|
needs: should-i-run
|
||||||
|
@ -282,42 +88,13 @@ jobs:
|
||||||
emulator.log
|
emulator.log
|
||||||
failure_screenshots/
|
failure_screenshots/
|
||||||
|
|
||||||
codecov-units:
|
|
||||||
name: Unit tests with code coverage
|
|
||||||
needs: should-i-run
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'adopt'
|
|
||||||
java-version: '11'
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
- run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
|
||||||
- name: Upload Codecov data
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: codecov-xml
|
|
||||||
path: |
|
|
||||||
build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
|
|
||||||
|
|
||||||
# Notify the channel about delayed failures
|
# Notify the channel about delayed failures
|
||||||
notify:
|
notify:
|
||||||
name: Notify matrix
|
name: Notify matrix
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- should-i-run
|
- should-i-run
|
||||||
- integration-tests
|
|
||||||
- ui-tests
|
- ui-tests
|
||||||
- codecov-units
|
|
||||||
if: always() && (needs.should-i-run.result == 'success' ) && ((needs.codecov-units.result != 'success' ) || (needs.ui-tests.result != 'success') || (needs.integration-tests.result != 'success'))
|
if: always() && (needs.should-i-run.result == 'success' ) && ((needs.codecov-units.result != 'success' ) || (needs.ui-tests.result != 'success') || (needs.integration-tests.result != 'success'))
|
||||||
# No concurrency required, runs every time on a schedule.
|
# No concurrency required, runs every time on a schedule.
|
||||||
steps:
|
steps:
|
||||||
|
|
81
.github/workflows/sonarqube.yml
vendored
81
.github/workflows/sonarqube.yml
vendored
|
@ -1,81 +0,0 @@
|
||||||
name: Sonarqube nightly
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 20 * * *'
|
|
||||||
|
|
||||||
# Enrich gradle.properties for CI/CD
|
|
||||||
env:
|
|
||||||
CI_GRADLE_ARG_PROPERTIES: >
|
|
||||||
-Porg.gradle.jvmargs=-Xmx4g
|
|
||||||
-Porg.gradle.parallel=false
|
|
||||||
jobs:
|
|
||||||
codecov-units:
|
|
||||||
name: Unit tests with code coverage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'adopt'
|
|
||||||
java-version: '11'
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
- run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
|
||||||
- name: Upload Codecov data
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: codecov-xml
|
|
||||||
path: |
|
|
||||||
build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
|
|
||||||
|
|
||||||
sonarqube:
|
|
||||||
name: Sonarqube upload
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- codecov-units
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'adopt'
|
|
||||||
java-version: '11'
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
- uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: codecov-xml # will restore to allCodeCoverageReport.xml by default; we restore to the same location in following tasks
|
|
||||||
- run: mkdir -p build/reports/jacoco/allCodeCoverageReport/
|
|
||||||
- run: mv allCodeCoverageReport.xml build/reports/jacoco/allCodeCoverageReport/
|
|
||||||
- run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
|
||||||
|
|
||||||
# Notify the channel about sonarqube failures
|
|
||||||
notify:
|
|
||||||
name: Notify matrix
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- sonarqube
|
|
||||||
- codecov-units
|
|
||||||
if: always() && (needs.sonarqube.result != 'success' || needs.codecov-units.result != 'success')
|
|
||||||
steps:
|
|
||||||
- uses: michaelkaye/matrix-hookshot-action@v1.0.0
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
hookshot_url: ${{ secrets.ELEMENT_ANDROID_HOOKSHOT_URL }}
|
|
||||||
text_template: "Sonarqube run (on ${{ github.ref }}): {{#each job_statuses }}{{#with this }}{{#if completed }} {{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
|
||||||
html_template: "Sonarqube run (on ${{ github.ref }}): {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion}} {{name}} <font color='{{color conclusion}}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
|
143
.github/workflows/tests.yml
vendored
143
.github/workflows/tests.yml
vendored
|
@ -12,73 +12,100 @@ env:
|
||||||
-Porg.gradle.parallel=false
|
-Porg.gradle.parallel=false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Build Android Tests
|
tests:
|
||||||
build-android-tests:
|
name: Runs all tests
|
||||||
name: Build Android Tests
|
runs-on: macos-latest # for the emulator
|
||||||
runs-on: ubuntu-latest
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'adopt'
|
|
||||||
java-version: 11
|
|
||||||
- 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: Build Android Tests
|
|
||||||
run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
|
||||||
|
|
||||||
unit-tests:
|
|
||||||
name: Run Unit Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
# Allow all jobs on main and develop. Just one per PR.
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
|
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
with:
|
||||||
path: |
|
fetch-depth: 0
|
||||||
~/.gradle/caches
|
- uses: actions/setup-java@v3
|
||||||
~/.gradle/wrapper
|
with:
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
distribution: 'adopt'
|
||||||
restore-keys: |
|
java-version: '11'
|
||||||
${{ runner.os }}-gradle-
|
- uses: gradle/gradle-build-action@v2
|
||||||
- name: Run unit tests
|
- uses: actions/setup-python@v3
|
||||||
run: ./gradlew clean test $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
- uses: michaelkaye/setup-matrix-synapse@v1.0.3
|
||||||
|
with:
|
||||||
|
uploadLogs: true
|
||||||
|
httpPort: 8080
|
||||||
|
disableRateLimiting: true
|
||||||
|
public_baseurl: "http://10.0.2.2:8080/"
|
||||||
|
- name: Run all the codecoverage tests at once
|
||||||
|
id: tests
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
api-level: 28
|
||||||
|
arch: x86
|
||||||
|
profile: Nexus 5X
|
||||||
|
force-avd-creation: false
|
||||||
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
|
disable-animations: true
|
||||||
|
emulator-build: 7425822
|
||||||
|
script: ./gradlew theCodeCoverageReport -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
|
||||||
|
- name: Run all the codecoverage tests at once (retry if emulator failed)
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
|
||||||
|
with:
|
||||||
|
api-level: 28
|
||||||
|
arch: x86
|
||||||
|
profile: Nexus 5X
|
||||||
|
force-avd-creation: false
|
||||||
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
|
disable-animations: true
|
||||||
|
emulator-build: 7425822
|
||||||
|
script: ./gradlew theCodeCoverageReport -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $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
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
|
||||||
- name: Format unit test results
|
- name: Format unit test results
|
||||||
if: always()
|
if: always()
|
||||||
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
|
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
|
||||||
- name: Publish Unit Test Results
|
|
||||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
|
||||||
if: always() &&
|
|
||||||
github.event.sender.login != 'dependabot[bot]' &&
|
|
||||||
( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
|
|
||||||
with:
|
|
||||||
files: ./**/build/test-results/**/*.xml
|
|
||||||
|
|
||||||
# Notify the channel about runs against develop or main that have failures, as PRs should have caught these first.
|
# can't be run on macos due to containers.
|
||||||
notify:
|
# - name: Publish Unit Test Results
|
||||||
runs-on: ubuntu-latest
|
# uses: EnricoMi/publish-unit-test-result-action@v1
|
||||||
needs:
|
# if: always() &&
|
||||||
- unit-tests
|
# github.event.sender.login != 'dependabot[bot]' &&
|
||||||
- build-android-tests
|
# ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
|
||||||
if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' ) && failure() }}
|
# with:
|
||||||
steps:
|
# files: ./**/build/test-results/**/*.xml
|
||||||
- uses: michaelkaye/matrix-hookshot-action@v0.3.0
|
|
||||||
with:
|
# Unneeded as part of the test suite above, kept around in case we want to re-enable them.
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
#
|
||||||
matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }}
|
# # Build Android Tests
|
||||||
matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }}
|
# build-android-tests:
|
||||||
text_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}{{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
# name: Build Android Tests
|
||||||
html_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion }} {{name}} <font color='{{color conclusion }}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
# runs-on: ubuntu-latest
|
||||||
|
# concurrency:
|
||||||
|
# group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
|
||||||
|
# cancel-in-progress: true
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v3
|
||||||
|
# - uses: actions/setup-java@v3
|
||||||
|
# with:
|
||||||
|
# distribution: 'adopt'
|
||||||
|
# java-version: 11
|
||||||
|
# - 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: Build Android Tests
|
||||||
|
# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||||
|
|
||||||
|
|
25
.github/workflows/triage-labelled.yml
vendored
25
.github/workflows/triage-labelled.yml
vendored
|
@ -9,15 +9,15 @@ jobs:
|
||||||
name: Add Z-Labs label for features behind labs flags
|
name: Add Z-Labs label for features behind labs flags
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: >
|
if: >
|
||||||
contains(github.event.issue.labels.*.name, 'A-Maths') ||
|
contains(github.event.issue.labels.*.name, 'A-Maths') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
|
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
||||||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
|
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
|
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
|
||||||
contains(github.event.issue.labels.*.name, 'A-Tags')
|
contains(github.event.issue.labels.*.name, 'A-Tags')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v5
|
- uses: actions/github-script@v5
|
||||||
with:
|
with:
|
||||||
|
@ -79,7 +79,7 @@ jobs:
|
||||||
name: X-Needs-Product to Design project board
|
name: X-Needs-Product to Design project board
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: >
|
if: >
|
||||||
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
|
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
|
||||||
steps:
|
steps:
|
||||||
- uses: octokit/graphql-action@v2.x
|
- uses: octokit/graphql-action@v2.x
|
||||||
id: add_to_project
|
id: add_to_project
|
||||||
|
@ -105,10 +105,7 @@ jobs:
|
||||||
# Skip in forks
|
# Skip in forks
|
||||||
if: >
|
if: >
|
||||||
github.repository == 'vector-im/element-android' &&
|
github.repository == 'vector-im/element-android' &&
|
||||||
(contains(github.event.issue.labels.*.name, 'A-Spaces') ||
|
(contains(github.event.issue.labels.*.name, 'Team: Delight'))
|
||||||
contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
|
|
||||||
contains(github.event.issue.labels.*.name, 'A-Subspaces') ||
|
|
||||||
contains(github.event.issue.labels.*.name, 'Z-IA'))
|
|
||||||
steps:
|
steps:
|
||||||
- uses: octokit/graphql-action@v2.x
|
- uses: octokit/graphql-action@v2.x
|
||||||
with:
|
with:
|
||||||
|
|
5
.github/workflows/triage-priority-bugs.yml
vendored
5
.github/workflows/triage-priority-bugs.yml
vendored
|
@ -14,10 +14,7 @@ jobs:
|
||||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
|
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
|
||||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
|
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
|
||||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
|
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
|
||||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
|
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
|
||||||
!contains(github.event.issue.labels.*.name, 'A-Spaces') &&
|
|
||||||
!contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
|
|
||||||
!contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
|
|
||||||
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
|
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
|
||||||
contains(github.event.issue.labels.*.name, 'S-Critical') &&
|
contains(github.event.issue.labels.*.name, 'S-Critical') &&
|
||||||
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
||||||
|
|
40
CHANGES.md
40
CHANGES.md
|
@ -1,3 +1,43 @@
|
||||||
|
Changes in Element v1.4.22 (2022-06-14)
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Features ✨
|
||||||
|
----------
|
||||||
|
- Make read receipt avatar list more compact ([#5970](https://github.com/vector-im/element-android/issues/5970))
|
||||||
|
- Allow .well-known configuration to override key sharing mode ([#6147](https://github.com/vector-im/element-android/issues/6147))
|
||||||
|
- Re-organize location settings flags ([#6244](https://github.com/vector-im/element-android/issues/6244))
|
||||||
|
- Add report action for live location messages ([#6280](https://github.com/vector-im/element-android/issues/6280))
|
||||||
|
|
||||||
|
Bugfixes 🐛
|
||||||
|
----------
|
||||||
|
- Fix cases of missing, swapped, or duplicated messages ([#5528](https://github.com/vector-im/element-android/issues/5528))
|
||||||
|
- Fix wrong status of live location sharing in timeline ([#6209](https://github.com/vector-im/element-android/issues/6209))
|
||||||
|
- Fix StackOverflowError while recording voice message ([#6222](https://github.com/vector-im/element-android/issues/6222))
|
||||||
|
- Text cropped: "Secure backup" ([#6232](https://github.com/vector-im/element-android/issues/6232))
|
||||||
|
- Fix copyright attributions of map views ([#6247](https://github.com/vector-im/element-android/issues/6247))
|
||||||
|
- Fix flickering bottom bar of live location item ([#6264](https://github.com/vector-im/element-android/issues/6264))
|
||||||
|
|
||||||
|
In development 🚧
|
||||||
|
----------------
|
||||||
|
- FTUE - Adds Sign Up tracking ([#5285](https://github.com/vector-im/element-android/issues/5285))
|
||||||
|
|
||||||
|
SDK API changes ⚠️
|
||||||
|
------------------
|
||||||
|
- Some methods from `Session` have been moved to a new `SyncService`, that you can retrieve from a `Session`.
|
||||||
|
- `SyncStatusService` method has been moved to the new `SyncService`
|
||||||
|
- `InitSyncStep` have been moved and renamed to `InitialSyncStep`
|
||||||
|
- `SyncStatusService.Status` has been renamed to `SyncRequestState`
|
||||||
|
- The existing `SyncService` has been renamed to `SyncAndroidService` because of name clash with the new SDK Service ([#6029](https://github.com/vector-im/element-android/issues/6029))
|
||||||
|
- Allows `AuthenticationService.getLoginFlow` to fail without resetting state from previously successful calls ([#6093](https://github.com/vector-im/element-android/issues/6093))
|
||||||
|
- Allows new passwords to be passed at the point of confirmation when resetting a password ([#6169](https://github.com/vector-im/element-android/issues/6169))
|
||||||
|
|
||||||
|
Other changes
|
||||||
|
-------------
|
||||||
|
- Adds support for parsing homeserver versions without a patch number ([#6017](https://github.com/vector-im/element-android/issues/6017))
|
||||||
|
- Updating exit onboarding dialog copy formatting to match iOS ([#6087](https://github.com/vector-im/element-android/issues/6087))
|
||||||
|
- Disables when arrow alignment in code style ([#6126](https://github.com/vector-im/element-android/issues/6126))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element 1.4.20 (2022-06-13)
|
Changes in Element 1.4.20 (2022-06-13)
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
[![Buildkite](https://badge.buildkite.com/ad0065c1b70f557cd3b1d3d68f9c2154010f83c4d6f71706a9.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
[![Buildkite](https://badge.buildkite.com/ad0065c1b70f557cd3b1d3d68f9c2154010f83c4d6f71706a9.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
||||||
[![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget)
|
[![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget)
|
||||||
[![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org)
|
[![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org)
|
||||||
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=alert_status)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||||
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||||
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=bugs)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||||
|
|
||||||
# Element Android
|
# Element Android
|
||||||
|
|
||||||
|
|
10
build.gradle
10
build.gradle
|
@ -25,7 +25,7 @@ buildscript {
|
||||||
classpath libs.gradle.kotlinPlugin
|
classpath libs.gradle.kotlinPlugin
|
||||||
classpath libs.gradle.hiltPlugin
|
classpath libs.gradle.hiltPlugin
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
|
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.google.android.gms:oss-licenses-plugin:0.10.5'
|
||||||
classpath "com.likethesalad.android:stem-plugin:2.1.1"
|
classpath "com.likethesalad.android:stem-plugin:2.1.1"
|
||||||
classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
|
classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
|
||||||
|
@ -43,7 +43,7 @@ plugins {
|
||||||
id "io.gitlab.arturbosch.detekt" version "1.20.0"
|
id "io.gitlab.arturbosch.detekt" version "1.20.0"
|
||||||
|
|
||||||
// Dependency Analysis
|
// Dependency Analysis
|
||||||
id 'com.autonomousapps.dependency-analysis' version "1.4.0"
|
id 'com.autonomousapps.dependency-analysis' version "1.5.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/jeremylong/DependencyCheck
|
// https://github.com/jeremylong/DependencyCheck
|
||||||
|
@ -180,8 +180,8 @@ apply plugin: 'org.sonarqube'
|
||||||
|
|
||||||
sonarqube {
|
sonarqube {
|
||||||
properties {
|
properties {
|
||||||
property "sonar.projectName", "Element-Android"
|
property "sonar.projectName", "element-android"
|
||||||
property "sonar.projectKey", "im.vector.app.android"
|
property "sonar.projectKey", "vector-im_element-android"
|
||||||
property "sonar.host.url", "https://sonarcloud.io"
|
property "sonar.host.url", "https://sonarcloud.io"
|
||||||
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
||||||
property "sonar.sourceEncoding", "UTF-8"
|
property "sonar.sourceEncoding", "UTF-8"
|
||||||
|
@ -191,7 +191,7 @@ sonarqube {
|
||||||
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
|
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
|
||||||
property "sonar.organization", "new_vector_ltd_organization"
|
property "sonar.organization", "new_vector_ltd_organization"
|
||||||
property "sonar.java.coveragePlugin", "jacoco"
|
property "sonar.java.coveragePlugin", "jacoco"
|
||||||
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml"
|
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/theCodeCoverageReport/theCodeCoverageReport.xml"
|
||||||
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,33 @@
|
||||||
def excludes = [ ]
|
def excludes = [
|
||||||
|
// dependency injection graph
|
||||||
|
'**/*Module.*',
|
||||||
|
'**/*Module*.*',
|
||||||
|
|
||||||
|
// Framework entry points
|
||||||
|
'**/*Activity*',
|
||||||
|
'**/*Fragment*',
|
||||||
|
'**/*Application*',
|
||||||
|
|
||||||
|
// We would like to exclude android widgets as well but our naming is inconsistent
|
||||||
|
|
||||||
|
// Proof of concept
|
||||||
|
'**/*Login2*',
|
||||||
|
|
||||||
|
// Generated
|
||||||
|
'**/*JsonAdapter*',
|
||||||
|
'**/*Item.*',
|
||||||
|
'**/*$Holder.*',
|
||||||
|
'**/*ViewHolder.*',
|
||||||
|
'**/*View.*',
|
||||||
|
'**/*BottomSheet.*'
|
||||||
|
]
|
||||||
|
|
||||||
def initializeReport(report, projects, classExcludes) {
|
def initializeReport(report, projects, classExcludes) {
|
||||||
projects.each { project -> project.apply plugin: 'jacoco' }
|
projects.each { project -> project.apply plugin: 'jacoco' }
|
||||||
report.executionData { fileTree(rootProject.rootDir.absolutePath).include("**/build/jacoco/*.exec") }
|
report.executionData { fileTree(rootProject.rootDir.absolutePath).include(
|
||||||
|
"**/build/outputs/unit_test_code_coverage/**/*.exec",
|
||||||
|
"**/build/outputs/code_coverage/**/coverage.ec"
|
||||||
|
) }
|
||||||
|
|
||||||
report.reports {
|
report.reports {
|
||||||
xml.enabled true
|
xml.enabled true
|
||||||
|
@ -18,11 +43,13 @@ def initializeReport(report, projects, classExcludes) {
|
||||||
switch (project) {
|
switch (project) {
|
||||||
case { project.plugins.hasPlugin("com.android.application") }:
|
case { project.plugins.hasPlugin("com.android.application") }:
|
||||||
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug")
|
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug")
|
||||||
|
androidSourceDirs.add("${project.buildDir}/generated/source/kapt/gplayDebug")
|
||||||
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
|
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
|
||||||
androidSourceDirs.add("${project.projectDir}/src/main/java")
|
androidSourceDirs.add("${project.projectDir}/src/main/java")
|
||||||
break
|
break
|
||||||
case { project.plugins.hasPlugin("com.android.library") }:
|
case { project.plugins.hasPlugin("com.android.library") }:
|
||||||
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug")
|
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug")
|
||||||
|
androidSourceDirs.add("${project.buildDir}/generated/source/kapt/debug")
|
||||||
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
|
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
|
||||||
androidSourceDirs.add("${project.projectDir}/src/main/java")
|
androidSourceDirs.add("${project.projectDir}/src/main/java")
|
||||||
break
|
break
|
||||||
|
@ -43,13 +70,18 @@ def collectProjects(predicate) {
|
||||||
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
|
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
task allCodeCoverageReport(type: JacocoReport) {
|
task theCodeCoverageReport(type: JacocoReport) {
|
||||||
outputs.upToDateWhen { false }
|
outputs.upToDateWhen { false }
|
||||||
rootProject.apply plugin: 'jacoco'
|
rootProject.apply plugin: 'jacoco'
|
||||||
// to limit projects in a specific report, add
|
tasks.withType(Test) {
|
||||||
// def excludedProjects = [ ... ]
|
jacoco.includeNoLocationClasses = true
|
||||||
// def projects = collectProjects { !excludedProjects.contains(it.name) }
|
}
|
||||||
def projects = collectProjects { true }
|
def projects = collectProjects { ['vector','matrix-sdk-android'].contains(it.name) }
|
||||||
dependsOn { projects*.test }
|
dependsOn {
|
||||||
|
[':vector:testGplayDebugUnitTest'] +
|
||||||
|
[':vector:connectedGplayDebugAndroidTest'] +
|
||||||
|
[':matrix-sdk-android:testDebugUnitTest'] +
|
||||||
|
[':matrix-sdk-android:connectedDebugAndroidTest']
|
||||||
|
}
|
||||||
initializeReport(it, projects, excludes)
|
initializeReport(it, projects, excludes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ ext.libs = [
|
||||||
],
|
],
|
||||||
androidx : [
|
androidx : [
|
||||||
'activity' : "androidx.activity:activity:1.4.0",
|
'activity' : "androidx.activity:activity:1.4.0",
|
||||||
'appCompat' : "androidx.appcompat:appcompat:1.4.1",
|
'appCompat' : "androidx.appcompat:appcompat:1.4.2",
|
||||||
'core' : "androidx.core:core-ktx:1.7.0",
|
'core' : "androidx.core:core-ktx:1.8.0",
|
||||||
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
||||||
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
|
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
|
||||||
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1",
|
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1",
|
||||||
|
@ -78,7 +78,7 @@ ext.libs = [
|
||||||
'transition' : "androidx.transition:transition:1.2.0",
|
'transition' : "androidx.transition:transition:1.2.0",
|
||||||
],
|
],
|
||||||
google : [
|
google : [
|
||||||
'material' : "com.google.android.material:material:1.6.0"
|
'material' : "com.google.android.material:material:1.6.1"
|
||||||
],
|
],
|
||||||
dagger : [
|
dagger : [
|
||||||
'dagger' : "com.google.dagger:dagger:$dagger",
|
'dagger' : "com.google.dagger:dagger:$dagger",
|
||||||
|
|
|
@ -1,64 +1,49 @@
|
||||||
fastlane documentation
|
fastlane documentation
|
||||||
----
|
================
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
Make sure you have the latest version of the Xcode command line tools installed:
|
Make sure you have the latest version of the Xcode command line tools installed:
|
||||||
|
|
||||||
```sh
|
```
|
||||||
xcode-select --install
|
xcode-select --install
|
||||||
```
|
```
|
||||||
|
|
||||||
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
|
Install _fastlane_ using
|
||||||
|
```
|
||||||
|
[sudo] gem install fastlane -NV
|
||||||
|
```
|
||||||
|
or alternatively using `brew install fastlane`
|
||||||
|
|
||||||
# Available Actions
|
# Available Actions
|
||||||
|
|
||||||
## Android
|
## Android
|
||||||
|
|
||||||
### android test
|
### android test
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android test
|
|
||||||
```
|
```
|
||||||
|
fastlane android test
|
||||||
|
```
|
||||||
Runs all the tests
|
Runs all the tests
|
||||||
|
|
||||||
### android beta
|
### android beta
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android beta
|
|
||||||
```
|
```
|
||||||
|
fastlane android beta
|
||||||
|
```
|
||||||
Submit a new Beta Build to Crashlytics Beta
|
Submit a new Beta Build to Crashlytics Beta
|
||||||
|
|
||||||
### android deploy
|
### android deploy
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android deploy
|
|
||||||
```
|
```
|
||||||
|
fastlane android deploy
|
||||||
|
```
|
||||||
Deploy a new version to the Google Play
|
Deploy a new version to the Google Play
|
||||||
|
|
||||||
### android deployMeta
|
### android deployMeta
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android deployMeta
|
|
||||||
```
|
```
|
||||||
|
fastlane android deployMeta
|
||||||
|
```
|
||||||
Deploy Google Play metadata
|
Deploy Google Play metadata
|
||||||
|
|
||||||
### android getVersionCode
|
### android getVersionCode
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android getVersionCode
|
|
||||||
```
|
```
|
||||||
|
fastlane android getVersionCode
|
||||||
|
```
|
||||||
Get version code
|
Get version code
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
|
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
|
||||||
|
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
|
||||||
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
|
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
|
||||||
|
|
||||||
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
|
|
||||||
|
|
2
fastlane/metadata/android/cs-CZ/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/cs-CZ/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Hlavní změny v této verzi: Vylepšena správa šifrovaných zpráv. Opravy různých chyb a vylepšení stability.
|
||||||
|
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/en-US/changelogs/40104220.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40104220.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
|
2
fastlane/metadata/android/et/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/et/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Põhilised muutused selles versioonis: krüptitud sõnumite parem haldus, lisaks pisiparandused ja stabiilsust parandavad kohendused.
|
||||||
|
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fa/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/fa/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
تغییرات عمده در این نگارش: مدیریت بهتر پیامهای رمزگذاشته. رفع اشکالهای مختلف و بهبودهای پایداری.
|
||||||
|
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fr-FR/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/fr-FR/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Principaux changements pour cette version : Meilleure gestion des messages chiffrés. Plusieurs corrections de bogues et d’améliorations de stabilité.
|
||||||
|
Intégralité des changements : https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/id/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/id/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Perubahan utama dalam versi ini: Pengelolaan pesan terenkripsi lebih baik. Banyak perbaikan kutu dan perbaikan stabilitas.
|
||||||
|
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/it-IT/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/it-IT/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Modifiche principali in questa versione: migliorata la gestione dei messaggi cifrati. Varie correzioni e miglioramenti della stabilità.
|
||||||
|
Cronologia completa: https://github.com/vector-im/element-android/releases
|
|
@ -1 +1 @@
|
||||||
אלמנט (בעבר Riot.im)
|
אלמנט - התכתבות מאובטחת
|
||||||
|
|
2
fastlane/metadata/android/pl-PL/changelogs/40101060.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101060.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wesji: poprawki dla wesji 1.1.5
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.6
|
2
fastlane/metadata/android/pl-PL/changelogs/40101070.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101070.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Eksperymentalne wsparcie dla przestrzeni, Kompresowanie video przed wysłaniem.
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.7
|
2
fastlane/metadata/android/pl-PL/changelogs/40101080.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101080.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Poprawki w przestrzeniach
|
||||||
|
Pełna lista zmian https://github.com/vector-im/element-android/releases/tag/v1.1.8
|
2
fastlane/metadata/android/pl-PL/changelogs/40101090.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101090.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Dodano wsparcie dla sieci gitter.im .
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.9
|
2
fastlane/metadata/android/pl-PL/changelogs/40101100.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101100.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Nowe funkcje dla przestrzeni i aktualizacja motywu i stylu.
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
2
fastlane/metadata/android/pl-PL/changelogs/40101110.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40101110.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Dodano nowe funkcje do przestrzeni i zaktualizowano motyw i styl aplikacji. (poprawki błędóœ dla wesji 1.1.10)
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
2
fastlane/metadata/android/pl-PL/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Główne zmiany w tej wersji: Lepsze zarządzanie zaszyfrowanymi wiadomościami. , Poprawki błędów i stabilności.
|
||||||
|
Pełna lista zmian: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/pt-BR/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/pt-BR/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Principais mudanças nesta versão: Melhor gerenciamento de mensagens encriptadas. Vários consertos de bugs e melhorias de estabilidade.
|
||||||
|
Changelog completo: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/sk/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/sk/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Hlavné zmeny v tejto verzii: Lepšia spravovanie zašifrovaných správ. Rôzne opravy chýb a vylepšenia stability.
|
||||||
|
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/sv-SE/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/sv-SE/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Huvudsakliga ändringar i den här versionen: Bättre hantering av krypterade meddelanden. Diverse buggfixar och stabilitetsförbättringar.
|
||||||
|
Full ändringslogg: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/uk/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Основні зміни в цій версії: Поліпшено керування зашифрованими повідомленнями. Усунуто різні вади й поліпшено стабільність.
|
||||||
|
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/zh-TW/changelogs/40104160.txt
Normal file
2
fastlane/metadata/android/zh-TW/changelogs/40104160.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要變動:對於被加密的訊息有更好的管理方式。多個臭蟲修復與穩定性改善。
|
||||||
|
完整的變更紀錄:https://github.com/vector-im/element-android/releases
|
|
@ -271,7 +271,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
||||||
directionDetector.handleTouchEvent(event)
|
directionDetector.handleTouchEvent(event)
|
||||||
|
|
||||||
return when (swipeDirection) {
|
return when (swipeDirection) {
|
||||||
SwipeDirection.Up, SwipeDirection.Down -> {
|
SwipeDirection.Up, SwipeDirection.Down -> {
|
||||||
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
|
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
|
||||||
swipeDismissHandler.onTouch(views.rootContainer, event)
|
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||||
} else true
|
} else true
|
||||||
|
@ -279,7 +279,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
||||||
SwipeDirection.Left, SwipeDirection.Right -> {
|
SwipeDirection.Left, SwipeDirection.Right -> {
|
||||||
views.attachmentPager.dispatchTouchEvent(event)
|
views.attachmentPager.dispatchTouchEvent(event)
|
||||||
}
|
}
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,18 +42,18 @@ class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
val itemView = inflater.inflate(viewType, parent, false)
|
val itemView = inflater.inflate(viewType, parent, false)
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
|
R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
|
||||||
R.layout.item_animated_image_attachment -> AnimatedImageViewHolder(itemView)
|
R.layout.item_animated_image_attachment -> AnimatedImageViewHolder(itemView)
|
||||||
R.layout.item_video_attachment -> VideoViewHolder(itemView)
|
R.layout.item_video_attachment -> VideoViewHolder(itemView)
|
||||||
else -> UnsupportedViewHolder(itemView)
|
else -> UnsupportedViewHolder(itemView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
val info = attachmentSourceProvider!!.getAttachmentInfoAt(position)
|
val info = attachmentSourceProvider!!.getAttachmentInfoAt(position)
|
||||||
return when (info) {
|
return when (info) {
|
||||||
is AttachmentInfo.Image -> R.layout.item_image_attachment
|
is AttachmentInfo.Image -> R.layout.item_image_attachment
|
||||||
is AttachmentInfo.Video -> R.layout.item_video_attachment
|
is AttachmentInfo.Video -> R.layout.item_video_attachment
|
||||||
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
|
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
|
||||||
// is AttachmentInfo.Audio -> TODO()
|
// is AttachmentInfo.Audio -> TODO()
|
||||||
// is AttachmentInfo.File -> TODO()
|
// is AttachmentInfo.File -> TODO()
|
||||||
|
@ -68,13 +68,13 @@ class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
||||||
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
|
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
|
||||||
holder.bind(it)
|
holder.bind(it)
|
||||||
when (it) {
|
when (it) {
|
||||||
is AttachmentInfo.Image -> {
|
is AttachmentInfo.Image -> {
|
||||||
attachmentSourceProvider?.loadImage((holder as ZoomableImageViewHolder).target, it)
|
attachmentSourceProvider?.loadImage((holder as ZoomableImageViewHolder).target, it)
|
||||||
}
|
}
|
||||||
is AttachmentInfo.AnimatedImage -> {
|
is AttachmentInfo.AnimatedImage -> {
|
||||||
attachmentSourceProvider?.loadImage((holder as AnimatedImageViewHolder).target, it)
|
attachmentSourceProvider?.loadImage((holder as AnimatedImageViewHolder).target, it)
|
||||||
}
|
}
|
||||||
is AttachmentInfo.Video -> {
|
is AttachmentInfo.Video -> {
|
||||||
attachmentSourceProvider?.loadVideo((holder as VideoViewHolder).target, it)
|
attachmentSourceProvider?.loadVideo((holder as VideoViewHolder).target, it)
|
||||||
}
|
}
|
||||||
// else -> {
|
// else -> {
|
||||||
|
|
|
@ -27,12 +27,12 @@ sealed class SwipeDirection {
|
||||||
companion object {
|
companion object {
|
||||||
fun fromAngle(angle: Double): SwipeDirection {
|
fun fromAngle(angle: Double): SwipeDirection {
|
||||||
return when (angle) {
|
return when (angle) {
|
||||||
in 0.0..45.0 -> Right
|
in 0.0..45.0 -> Right
|
||||||
in 45.0..135.0 -> Up
|
in 45.0..135.0 -> Up
|
||||||
in 135.0..225.0 -> Left
|
in 135.0..225.0 -> Left
|
||||||
in 225.0..315.0 -> Down
|
in 225.0..315.0 -> Down
|
||||||
in 315.0..360.0 -> Right
|
in 315.0..360.0 -> Right
|
||||||
else -> NotDetected
|
else -> NotDetected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class SwipeDirectionDetector(
|
||||||
|
|
||||||
fun handleTouchEvent(event: MotionEvent) {
|
fun handleTouchEvent(event: MotionEvent) {
|
||||||
when (event.action) {
|
when (event.action) {
|
||||||
MotionEvent.ACTION_DOWN -> {
|
MotionEvent.ACTION_DOWN -> {
|
||||||
startX = event.x
|
startX = event.x
|
||||||
startY = event.y
|
startY = event.y
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class SwipeDirectionDetector(
|
||||||
startX = startY
|
startX = startY
|
||||||
isDetected = false
|
isDetected = false
|
||||||
}
|
}
|
||||||
MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
|
MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
|
||||||
isDetected = true
|
isDetected = true
|
||||||
onDirectionDetected(getDirection(startX, startY, event.x, event.y))
|
onDirectionDetected(getDirection(startX, startY, event.x, event.y))
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class SwipeToDismissHandler(
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||||
when (event.action) {
|
when (event.action) {
|
||||||
MotionEvent.ACTION_DOWN -> {
|
MotionEvent.ACTION_DOWN -> {
|
||||||
if (swipeView.hitRect.contains(event.x.toInt(), event.y.toInt())) {
|
if (swipeView.hitRect.contains(event.x.toInt(), event.y.toInt())) {
|
||||||
isTracking = true
|
isTracking = true
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class SwipeToDismissHandler(
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
MotionEvent.ACTION_MOVE -> {
|
MotionEvent.ACTION_MOVE -> {
|
||||||
if (isTracking) {
|
if (isTracking) {
|
||||||
val translationY = event.y - startY
|
val translationY = event.y - startY
|
||||||
swipeView.translationY = translationY
|
swipeView.translationY = translationY
|
||||||
|
@ -66,7 +66,7 @@ class SwipeToDismissHandler(
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ class SwipeToDismissHandler(
|
||||||
private fun onTrackingEnd(parentHeight: Int) {
|
private fun onTrackingEnd(parentHeight: Int) {
|
||||||
val animateTo = when {
|
val animateTo = when {
|
||||||
swipeView.translationY < -translationLimit -> -parentHeight.toFloat()
|
swipeView.translationY < -translationLimit -> -parentHeight.toFloat()
|
||||||
swipeView.translationY > translationLimit -> parentHeight.toFloat()
|
swipeView.translationY > translationLimit -> parentHeight.toFloat()
|
||||||
else -> 0f
|
else -> 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animateTo != 0f && !shouldAnimateDismiss()) {
|
if (animateTo != 0f && !shouldAnimateDismiss()) {
|
||||||
|
|
|
@ -146,7 +146,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
wasPaused = true
|
wasPaused = true
|
||||||
views.videoView.pause()
|
views.videoView.pause()
|
||||||
}
|
}
|
||||||
is AttachmentCommands.SeekTo -> {
|
is AttachmentCommands.SeekTo -> {
|
||||||
val duration = views.videoView.duration
|
val duration = views.videoView.duration
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
val seekDuration = duration * (commands.percentProgress / 100f)
|
val seekDuration = duration * (commands.percentProgress / 100f)
|
||||||
|
|
|
@ -43,7 +43,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
||||||
text(async.error.localizedMessage?.toEpoxyCharSequence())
|
text(async.error.localizedMessage?.toEpoxyCharSequence())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
async.invoke()?.let {
|
async.invoke()?.let {
|
||||||
buildRec(it, 0, "")
|
buildRec(it, 0, "")
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is JSonViewerArray -> {
|
is JSonViewerArray -> {
|
||||||
if (model.isExpanded) {
|
if (model.isExpanded) {
|
||||||
open(id, model.key, model.index, depth, false, model)
|
open(id, model.key, model.index, depth, false, model)
|
||||||
model.items.forEach {
|
model.items.forEach {
|
||||||
|
@ -137,7 +137,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is JSonViewerLeaf -> {
|
is JSonViewerLeaf -> {
|
||||||
valueItem {
|
valueItem {
|
||||||
id(id)
|
id(id)
|
||||||
depth(depth)
|
depth(depth)
|
||||||
|
@ -172,12 +172,12 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
||||||
private fun valueToSpan(leaf: JSonViewerLeaf): Span {
|
private fun valueToSpan(leaf: JSonViewerLeaf): Span {
|
||||||
val host = this
|
val host = this
|
||||||
return when (leaf.type) {
|
return when (leaf.type) {
|
||||||
JSONType.STRING -> {
|
JSONType.STRING -> {
|
||||||
span("\"${leaf.stringRes}\"") {
|
span("\"${leaf.stringRes}\"") {
|
||||||
textColor = host.styleProvider.stringColor
|
textColor = host.styleProvider.stringColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSONType.NUMBER -> {
|
JSONType.NUMBER -> {
|
||||||
span(leaf.stringRes) {
|
span(leaf.stringRes) {
|
||||||
textColor = host.styleProvider.numberColor
|
textColor = host.styleProvider.numberColor
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
|
||||||
textColor = host.styleProvider.booleanColor
|
textColor = host.styleProvider.booleanColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSONType.NULL -> {
|
JSONType.NULL -> {
|
||||||
span("null") {
|
span("null") {
|
||||||
textColor = host.styleProvider.booleanColor
|
textColor = host.styleProvider.booleanColor
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ internal object ModelParser {
|
||||||
}
|
}
|
||||||
parent.addChild(objectComposed)
|
parent.addChild(objectComposed)
|
||||||
}
|
}
|
||||||
is JSONArray -> {
|
is JSONArray -> {
|
||||||
val objectComposed = JSonViewerArray(key, index, obj)
|
val objectComposed = JSonViewerArray(key, index, obj)
|
||||||
.apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth }
|
.apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth }
|
||||||
objectComposed.depth = depth
|
objectComposed.depth = depth
|
||||||
|
@ -91,25 +91,25 @@ internal object ModelParser {
|
||||||
}
|
}
|
||||||
parent.addChild(objectComposed)
|
parent.addChild(objectComposed)
|
||||||
}
|
}
|
||||||
is String -> {
|
is String -> {
|
||||||
JSonViewerLeaf(key, index, obj, JSONType.STRING).let {
|
JSonViewerLeaf(key, index, obj, JSONType.STRING).let {
|
||||||
it.depth = depth
|
it.depth = depth
|
||||||
parent.addChild(it)
|
parent.addChild(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Number -> {
|
is Number -> {
|
||||||
JSonViewerLeaf(key, index, obj.toString(), JSONType.NUMBER).let {
|
JSonViewerLeaf(key, index, obj.toString(), JSONType.NUMBER).let {
|
||||||
it.depth = depth
|
it.depth = depth
|
||||||
parent.addChild(it)
|
parent.addChild(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Boolean -> {
|
is Boolean -> {
|
||||||
JSonViewerLeaf(key, index, obj.toString(), JSONType.BOOLEAN).let {
|
JSonViewerLeaf(key, index, obj.toString(), JSONType.BOOLEAN).let {
|
||||||
it.depth = depth
|
it.depth = depth
|
||||||
parent.addChild(it)
|
parent.addChild(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (obj == JSONObject.NULL) {
|
if (obj == JSONObject.NULL) {
|
||||||
JSonViewerLeaf(key, index, "null", JSONType.NULL).let {
|
JSonViewerLeaf(key, index, "null", JSONType.NULL).let {
|
||||||
it.depth = depth
|
it.depth = depth
|
||||||
|
|
|
@ -48,7 +48,7 @@ class FilePicker : Picker<MultiPickerBaseType>() {
|
||||||
type.isMimeTypeVideo() -> selectedUri.toMultiPickerVideoType(context)
|
type.isMimeTypeVideo() -> selectedUri.toMultiPickerVideoType(context)
|
||||||
type.isMimeTypeImage() -> selectedUri.toMultiPickerImageType(context)
|
type.isMimeTypeImage() -> selectedUri.toMultiPickerImageType(context)
|
||||||
type.isMimeTypeAudio() -> selectedUri.toMultiPickerAudioType(context)
|
type.isMimeTypeAudio() -> selectedUri.toMultiPickerAudioType(context)
|
||||||
else -> {
|
else -> {
|
||||||
// Other files
|
// Other files
|
||||||
context.contentResolver.query(selectedUri, null, null, null, null)
|
context.contentResolver.query(selectedUri, null, null, null, null)
|
||||||
?.use { cursor ->
|
?.use { cursor ->
|
||||||
|
|
|
@ -31,15 +31,15 @@ class MultiPicker<T> private constructor() {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T> get(type: MultiPicker<T>): T {
|
fun <T> get(type: MultiPicker<T>): T {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
IMAGE -> ImagePicker() as T
|
IMAGE -> ImagePicker() as T
|
||||||
VIDEO -> VideoPicker() as T
|
VIDEO -> VideoPicker() as T
|
||||||
MEDIA -> MediaPicker() as T
|
MEDIA -> MediaPicker() as T
|
||||||
FILE -> FilePicker() as T
|
FILE -> FilePicker() as T
|
||||||
AUDIO -> AudioPicker() as T
|
AUDIO -> AudioPicker() as T
|
||||||
CONTACT -> ContactPicker() as T
|
CONTACT -> ContactPicker() as T
|
||||||
CAMERA -> CameraPicker() as T
|
CAMERA -> CameraPicker() as T
|
||||||
CAMERA_VIDEO -> CameraVideoPicker() as T
|
CAMERA_VIDEO -> CameraVideoPicker() as T
|
||||||
else -> throw IllegalArgumentException("Unsupported type $type")
|
else -> throw IllegalArgumentException("Unsupported type $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<dimen name="text_size_body">14sp</dimen>
|
<dimen name="text_size_body">14sp</dimen>
|
||||||
<dimen name="text_size_caption">12sp</dimen>
|
<dimen name="text_size_caption">12sp</dimen>
|
||||||
<dimen name="text_size_micro">10sp</dimen>
|
<dimen name="text_size_micro">10sp</dimen>
|
||||||
|
<dimen name="text_size_nano">8sp</dimen>
|
||||||
|
|
||||||
<dimen name="text_size_button">14sp</dimen>
|
<dimen name="text_size_button">14sp</dimen>
|
||||||
|
|
||||||
|
|
|
@ -40,4 +40,9 @@
|
||||||
<item name="android:gravity">center</item>
|
<item name="android:gravity">center</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Vector.TextView.Nano.Copyright">
|
||||||
|
<!-- Static map view is always light in both light and dark theme. So we need to use a static dark color -->
|
||||||
|
<item name="android:textColor">@color/element_content_primary_light</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -48,4 +48,9 @@
|
||||||
<item name="lineHeight">16sp</item>
|
<item name="lineHeight">16sp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Vector.TextView.Nano">
|
||||||
|
<item name="android:textAppearance">@style/TextAppearance.Vector.Nano</item>
|
||||||
|
<item name="lineHeight">16sp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -85,4 +85,11 @@
|
||||||
<item name="android:letterSpacing">0.02</item>
|
<item name="android:letterSpacing">0.02</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Vector.Nano" parent="TextAppearance.MaterialComponents.Caption">
|
||||||
|
<item name="fontFamily">sans-serif</item>
|
||||||
|
<item name="android:fontFamily">sans-serif</item>
|
||||||
|
<item name="android:textSize">@dimen/text_size_nano</item>
|
||||||
|
<item name="android:letterSpacing">0</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -88,7 +88,7 @@ class FlowSession(private val session: Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveSyncState(): Flow<SyncState> {
|
fun liveSyncState(): Flow<SyncState> {
|
||||||
return session.getSyncStateLive().asFlow()
|
return session.syncService().getSyncStateLive().asFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun livePushers(): Flow<List<Pusher>> {
|
fun livePushers(): Flow<List<Pusher>> {
|
||||||
|
|
|
@ -56,7 +56,7 @@ android {
|
||||||
// that the app's state is completely cleared between tests.
|
// that the app's state is completely cleared between tests.
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
|
|
||||||
buildConfigField "String", "SDK_VERSION", "\"1.4.20\""
|
buildConfigField "String", "SDK_VERSION", "\"1.4.22\""
|
||||||
|
|
||||||
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
|
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
|
||||||
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
|
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
|
||||||
|
@ -74,6 +74,7 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
|
testCoverageEnabled true
|
||||||
// Set to true to log privacy or sensible data, such as token
|
// Set to true to log privacy or sensible data, such as token
|
||||||
buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData")
|
buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData")
|
||||||
// Set to BODY instead of NONE to enable logging
|
// Set to BODY instead of NONE to enable logging
|
||||||
|
@ -151,7 +152,7 @@ dependencies {
|
||||||
// - https://github.com/square/okhttp/issues/3278
|
// - https://github.com/square/okhttp/issues/3278
|
||||||
// - https://github.com/square/okhttp/issues/4455
|
// - https://github.com/square/okhttp/issues/4455
|
||||||
// - https://github.com/square/okhttp/issues/3146
|
// - https://github.com/square/okhttp/issues/3146
|
||||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
|
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ dependencies {
|
||||||
implementation libs.androidx.work
|
implementation libs.androidx.work
|
||||||
|
|
||||||
// olm lib is now hosted in MavenCentral
|
// olm lib is now hosted in MavenCentral
|
||||||
implementation 'org.matrix.android:olm-sdk:3.2.11'
|
implementation 'org.matrix.android:olm-sdk:3.2.12'
|
||||||
|
|
||||||
// DI
|
// DI
|
||||||
implementation libs.dagger.dagger
|
implementation libs.dagger.dagger
|
||||||
|
@ -192,7 +193,7 @@ dependencies {
|
||||||
implementation libs.apache.commonsImaging
|
implementation libs.apache.commonsImaging
|
||||||
|
|
||||||
// Phone number https://github.com/google/libphonenumber
|
// Phone number https://github.com/google/libphonenumber
|
||||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.49'
|
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.50'
|
||||||
|
|
||||||
testImplementation libs.tests.junit
|
testImplementation libs.tests.junit
|
||||||
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
|
|
|
@ -19,10 +19,14 @@ package org.matrix.android.sdk
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
import org.matrix.android.sdk.common.RetryTestRule
|
||||||
import org.matrix.android.sdk.test.shared.createTimberTestRule
|
import org.matrix.android.sdk.test.shared.createTimberTestRule
|
||||||
|
|
||||||
interface InstrumentedTest {
|
interface InstrumentedTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
fun retryTestRule() = RetryTestRule(3)
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
fun timberTestRule() = createTimberTestRule()
|
fun timberTestRule() = createTimberTestRule()
|
||||||
|
|
||||||
|
|
|
@ -137,11 +137,11 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
|
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
session.startSync(true)
|
session.syncService().startSync(true)
|
||||||
val syncLiveData = session.getSyncStateLive()
|
val syncLiveData = session.syncService().getSyncStateLive()
|
||||||
val syncObserver = object : Observer<SyncState> {
|
val syncObserver = object : Observer<SyncState> {
|
||||||
override fun onChanged(t: SyncState?) {
|
override fun onChanged(t: SyncState?) {
|
||||||
if (session.hasAlreadySynced()) {
|
if (session.syncService().hasAlreadySynced()) {
|
||||||
lock.countDown()
|
lock.countDown()
|
||||||
syncLiveData.removeObserver(this)
|
syncLiveData.removeObserver(this)
|
||||||
}
|
}
|
||||||
|
@ -160,10 +160,10 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
|
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
|
||||||
waitWithLatch(timeout) { latch ->
|
waitWithLatch(timeout) { latch ->
|
||||||
session.clearCache()
|
session.clearCache()
|
||||||
val syncLiveData = session.getSyncStateLive()
|
val syncLiveData = session.syncService().getSyncStateLive()
|
||||||
val syncObserver = object : Observer<SyncState> {
|
val syncObserver = object : Observer<SyncState> {
|
||||||
override fun onChanged(t: SyncState?) {
|
override fun onChanged(t: SyncState?) {
|
||||||
if (session.hasAlreadySynced()) {
|
if (session.syncService().hasAlreadySynced()) {
|
||||||
Timber.v("Clear cache and synced")
|
Timber.v("Clear cache and synced")
|
||||||
syncLiveData.removeObserver(this)
|
syncLiveData.removeObserver(this)
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
|
@ -171,7 +171,7 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syncLiveData.observeForever(syncObserver)
|
syncLiveData.observeForever(syncObserver)
|
||||||
session.startSync(true)
|
session.syncService().startSync(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +252,8 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
message: String,
|
message: String,
|
||||||
numberOfMessages: Int,
|
numberOfMessages: Int,
|
||||||
rootThreadEventId: String,
|
rootThreadEventId: String,
|
||||||
timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
|
timeout: Long = TestConstants.timeOutMillis
|
||||||
|
): List<TimelineEvent> {
|
||||||
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
|
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
|
||||||
timeline.start()
|
timeline.start()
|
||||||
val sentEvents = sendTextMessagesBatched(timeline, room, message, numberOfMessages, timeout, rootThreadEventId)
|
val sentEvents = sendTextMessagesBatched(timeline, room, message, numberOfMessages, timeout, rootThreadEventId)
|
||||||
|
@ -272,9 +273,11 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
* @param testParams test params about the session
|
* @param testParams test params about the session
|
||||||
* @return the session associated with the newly created account
|
* @return the session associated with the newly created account
|
||||||
*/
|
*/
|
||||||
private fun createAccount(userNamePrefix: String,
|
private fun createAccount(
|
||||||
password: String,
|
userNamePrefix: String,
|
||||||
testParams: SessionTestParams): Session {
|
password: String,
|
||||||
|
testParams: SessionTestParams
|
||||||
|
): Session {
|
||||||
val session = createAccountAndSync(
|
val session = createAccountAndSync(
|
||||||
userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(),
|
userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(),
|
||||||
password,
|
password,
|
||||||
|
@ -294,9 +297,11 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
* @param testParams test params about the session
|
* @param testParams test params about the session
|
||||||
* @return the session associated with the existing account
|
* @return the session associated with the existing account
|
||||||
*/
|
*/
|
||||||
fun logIntoAccount(userId: String,
|
fun logIntoAccount(
|
||||||
password: String,
|
userId: String,
|
||||||
testParams: SessionTestParams): Session {
|
password: String,
|
||||||
|
testParams: SessionTestParams
|
||||||
|
): Session {
|
||||||
val session = logAccountAndSync(userId, password, testParams)
|
val session = logAccountAndSync(userId, password, testParams)
|
||||||
assertNotNull(session)
|
assertNotNull(session)
|
||||||
return session.also {
|
return session.also {
|
||||||
|
@ -311,9 +316,11 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
* @param password the password
|
* @param password the password
|
||||||
* @param sessionTestParams parameters for the test
|
* @param sessionTestParams parameters for the test
|
||||||
*/
|
*/
|
||||||
private fun createAccountAndSync(userName: String,
|
private fun createAccountAndSync(
|
||||||
password: String,
|
userName: String,
|
||||||
sessionTestParams: SessionTestParams): Session {
|
password: String,
|
||||||
|
sessionTestParams: SessionTestParams
|
||||||
|
): Session {
|
||||||
val hs = createHomeServerConfig()
|
val hs = createHomeServerConfig()
|
||||||
|
|
||||||
runBlockingTest {
|
runBlockingTest {
|
||||||
|
@ -349,9 +356,11 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
* @param password the password
|
* @param password the password
|
||||||
* @param sessionTestParams session test params
|
* @param sessionTestParams session test params
|
||||||
*/
|
*/
|
||||||
private fun logAccountAndSync(userName: String,
|
private fun logAccountAndSync(
|
||||||
password: String,
|
userName: String,
|
||||||
sessionTestParams: SessionTestParams): Session {
|
password: String,
|
||||||
|
sessionTestParams: SessionTestParams
|
||||||
|
): Session {
|
||||||
val hs = createHomeServerConfig()
|
val hs = createHomeServerConfig()
|
||||||
|
|
||||||
runBlockingTest {
|
runBlockingTest {
|
||||||
|
@ -377,8 +386,10 @@ class CommonTestHelper private constructor(context: Context) {
|
||||||
* @param userName the account username
|
* @param userName the account username
|
||||||
* @param password the password
|
* @param password the password
|
||||||
*/
|
*/
|
||||||
fun logAccountWithError(userName: String,
|
fun logAccountWithError(
|
||||||
password: String): Throwable {
|
userName: String,
|
||||||
|
password: String
|
||||||
|
): Throwable {
|
||||||
val hs = createHomeServerConfig()
|
val hs = createHomeServerConfig()
|
||||||
|
|
||||||
runBlockingTest {
|
runBlockingTest {
|
||||||
|
|
|
@ -18,8 +18,10 @@ package org.matrix.android.sdk.common
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
data class CryptoTestData(val roomId: String,
|
data class CryptoTestData(
|
||||||
val sessions: List<Session>) {
|
val roomId: String,
|
||||||
|
val sessions: List<Session>
|
||||||
|
) {
|
||||||
|
|
||||||
val firstSession: Session
|
val firstSession: Session
|
||||||
get() = sessions.first()
|
get() = sessions.first()
|
||||||
|
|
|
@ -73,9 +73,11 @@ class MockOkHttpInterceptor : TestInterceptor {
|
||||||
/**
|
/**
|
||||||
* Simple rule that reply with the given body for any request that matches the match param
|
* Simple rule that reply with the given body for any request that matches the match param
|
||||||
*/
|
*/
|
||||||
class SimpleRule(match: String,
|
class SimpleRule(
|
||||||
private val code: Int = HttpsURLConnection.HTTP_OK,
|
match: String,
|
||||||
private val body: String = "{}") : Rule(match) {
|
private val code: Int = HttpsURLConnection.HTTP_OK,
|
||||||
|
private val body: String = "{}"
|
||||||
|
) : Rule(match) {
|
||||||
|
|
||||||
override fun process(originalRequest: Request): Response? {
|
override fun process(originalRequest: Request): Response? {
|
||||||
return Response.Builder()
|
return Response.Builder()
|
||||||
|
|
|
@ -27,8 +27,10 @@ import java.util.concurrent.CountDownLatch
|
||||||
* @param onlySuccessful true to fail if an error occurs. This is the default behavior
|
* @param onlySuccessful true to fail if an error occurs. This is the default behavior
|
||||||
* @param <T>
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
open class TestMatrixCallback<T>(private val countDownLatch: CountDownLatch,
|
open class TestMatrixCallback<T>(
|
||||||
private val onlySuccessful: Boolean = true) : MatrixCallback<T> {
|
private val countDownLatch: CountDownLatch,
|
||||||
|
private val onlySuccessful: Boolean = true
|
||||||
|
) : MatrixCallback<T> {
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
|
|
|
@ -47,7 +47,9 @@ internal interface TestMatrixComponent : MatrixComponent {
|
||||||
|
|
||||||
@Component.Factory
|
@Component.Factory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(@BindsInstance context: Context,
|
fun create(
|
||||||
@BindsInstance matrixConfiguration: MatrixConfiguration): TestMatrixComponent
|
@BindsInstance context: Context,
|
||||||
|
@BindsInstance matrixConfiguration: MatrixConfiguration
|
||||||
|
): TestMatrixComponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotEquals
|
import org.junit.Assert.assertNotEquals
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
|
@ -40,6 +41,7 @@ import java.util.UUID
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Ignore
|
||||||
class AttachmentEncryptionTest {
|
class AttachmentEncryptionTest {
|
||||||
|
|
||||||
private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {
|
private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotEquals
|
import org.junit.Assert.assertNotEquals
|
||||||
import org.junit.Assert.assertNull
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
@ -37,6 +38,7 @@ import org.matrix.olm.OlmSession
|
||||||
private const val DUMMY_DEVICE_KEY = "DeviceKey"
|
private const val DUMMY_DEVICE_KEY = "DeviceKey"
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@Ignore
|
||||||
class CryptoStoreTest : InstrumentedTest {
|
class CryptoStoreTest : InstrumentedTest {
|
||||||
|
|
||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
|
@ -626,7 +626,7 @@ class E2eeSanityTests : InstrumentedTest {
|
||||||
// we can release this latch?
|
// we can release this latch?
|
||||||
oldCompleteLatch.countDown()
|
oldCompleteLatch.countDown()
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -653,17 +653,17 @@ class E2eeSanityTests : InstrumentedTest {
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
||||||
// no need to accept as there was a request first it will auto accept
|
// no need to accept as there was a request first it will auto accept
|
||||||
}
|
}
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
||||||
if (matchOnce) {
|
if (matchOnce) {
|
||||||
sasTx.userHasVerifiedShortCode()
|
sasTx.userHasVerifiedShortCode()
|
||||||
newCode = sasTx.getDecimalCodeRepresentation()
|
newCode = sasTx.getDecimalCodeRepresentation()
|
||||||
matchOnce = false
|
matchOnce = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
||||||
newCompleteLatch.countDown()
|
newCompleteLatch.countDown()
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Assert.fail
|
import org.junit.Assert.fail
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
|
@ -30,6 +31,7 @@ import org.junit.runners.MethodSorters
|
||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Ignore
|
||||||
class ExportEncryptionTest {
|
class ExportEncryptionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -83,7 +85,8 @@ class ExportEncryptionTest {
|
||||||
@Test
|
@Test
|
||||||
fun checkExportDecrypt1() {
|
fun checkExportDecrypt1() {
|
||||||
val password = "password"
|
val password = "password"
|
||||||
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" + "cissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----"
|
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" +
|
||||||
|
"cissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----"
|
||||||
val expectedString = "plain"
|
val expectedString = "plain"
|
||||||
|
|
||||||
var decodedString: String? = null
|
var decodedString: String? = null
|
||||||
|
@ -103,7 +106,8 @@ class ExportEncryptionTest {
|
||||||
@Test
|
@Test
|
||||||
fun checkExportDecrypt2() {
|
fun checkExportDecrypt2() {
|
||||||
val password = "betterpassword"
|
val password = "betterpassword"
|
||||||
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" + "KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----"
|
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" +
|
||||||
|
"KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----"
|
||||||
val expectedString = "Hello, World"
|
val expectedString = "Hello, World"
|
||||||
|
|
||||||
var decodedString: String? = null
|
var decodedString: String? = null
|
||||||
|
@ -123,7 +127,8 @@ class ExportEncryptionTest {
|
||||||
@Test
|
@Test
|
||||||
fun checkExportDecrypt3() {
|
fun checkExportDecrypt3() {
|
||||||
val password = "SWORDFISH"
|
val password = "SWORDFISH"
|
||||||
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" + "MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----"
|
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" +
|
||||||
|
"MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----"
|
||||||
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
|
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
|
||||||
|
|
||||||
var decodedString: String? = null
|
var decodedString: String? = null
|
||||||
|
@ -202,7 +207,8 @@ class ExportEncryptionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun checkExportEncrypt4() {
|
fun checkExportEncrypt4() {
|
||||||
val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
|
val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||||
|
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
|
||||||
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
|
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
|
||||||
var decodedString: String? = null
|
var decodedString: String? = null
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.amshove.kluent.shouldBe
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
|
@ -59,6 +60,7 @@ import kotlin.coroutines.resume
|
||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
@Ignore
|
||||||
class UnwedgingTest : InstrumentedTest {
|
class UnwedgingTest : InstrumentedTest {
|
||||||
|
|
||||||
private lateinit var messagesReceivedByBob: List<TimelineEvent>
|
private lateinit var messagesReceivedByBob: List<TimelineEvent>
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.junit.Assert.assertNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Assert.fail
|
import org.junit.Assert.fail
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
|
@ -47,6 +48,7 @@ import kotlin.coroutines.resume
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore
|
||||||
class XSigningTest : InstrumentedTest {
|
class XSigningTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.amshove.kluent.internal.assertEquals
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Assert.assertNull
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
@ -50,6 +51,7 @@ import org.matrix.android.sdk.mustFail
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore
|
||||||
class KeyShareTests : InstrumentedTest {
|
class KeyShareTests : InstrumentedTest {
|
||||||
|
|
||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
@ -422,7 +424,7 @@ class KeyShareTests : InstrumentedTest {
|
||||||
|
|
||||||
// /!\ Stop initial alice session syncing so that it can't reply
|
// /!\ Stop initial alice session syncing so that it can't reply
|
||||||
aliceSession.cryptoService().enableKeyGossiping(false)
|
aliceSession.cryptoService().enableKeyGossiping(false)
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
|
|
||||||
// Let's now try to request
|
// Let's now try to request
|
||||||
aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root)
|
aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root)
|
||||||
|
@ -445,7 +447,7 @@ class KeyShareTests : InstrumentedTest {
|
||||||
|
|
||||||
// let's wake up alice
|
// let's wake up alice
|
||||||
aliceSession.cryptoService().enableKeyGossiping(true)
|
aliceSession.cryptoService().enableKeyGossiping(true)
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
|
|
||||||
// We should now get a reply from first session
|
// We should now get a reply from first session
|
||||||
commonTestHelper.waitWithLatch { latch ->
|
commonTestHelper.waitWithLatch { latch ->
|
||||||
|
|
|
@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.LargeTest
|
import androidx.test.filters.LargeTest
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
@ -46,6 +47,7 @@ import org.matrix.android.sdk.mustFail
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore
|
||||||
class WithHeldTests : InstrumentedTest {
|
class WithHeldTests : InstrumentedTest {
|
||||||
|
|
||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Assert.assertNull
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
@ -55,6 +56,7 @@ import java.util.concurrent.CountDownLatch
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore
|
||||||
class KeysBackupTest : InstrumentedTest {
|
class KeysBackupTest : InstrumentedTest {
|
||||||
|
|
||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
|
@ -33,7 +33,8 @@ import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
internal class KeysBackupTestHelper(
|
internal class KeysBackupTestHelper(
|
||||||
private val testHelper: CommonTestHelper,
|
private val testHelper: CommonTestHelper,
|
||||||
private val cryptoTestHelper: CryptoTestHelper) {
|
private val cryptoTestHelper: CryptoTestHelper
|
||||||
|
) {
|
||||||
|
|
||||||
fun waitForKeybackUpBatching() {
|
fun waitForKeybackUpBatching() {
|
||||||
Thread.sleep(400)
|
Thread.sleep(400)
|
||||||
|
@ -96,8 +97,10 @@ internal class KeysBackupTestHelper(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun prepareAndCreateKeysBackupData(keysBackup: KeysBackupService,
|
fun prepareAndCreateKeysBackupData(
|
||||||
password: String? = null): PrepareKeysBackupDataResult {
|
keysBackup: KeysBackupService,
|
||||||
|
password: String? = null
|
||||||
|
): PrepareKeysBackupDataResult {
|
||||||
val stateObserver = StateObserver(keysBackup)
|
val stateObserver = StateObserver(keysBackup)
|
||||||
|
|
||||||
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
||||||
|
@ -169,9 +172,11 @@ internal class KeysBackupTestHelper(
|
||||||
* - The new device must have the same count of megolm keys
|
* - The new device must have the same count of megolm keys
|
||||||
* - Alice must have the same keys on both devices
|
* - Alice must have the same keys on both devices
|
||||||
*/
|
*/
|
||||||
fun checkRestoreSuccess(testData: KeysBackupScenarioData,
|
fun checkRestoreSuccess(
|
||||||
total: Int,
|
testData: KeysBackupScenarioData,
|
||||||
imported: Int) {
|
total: Int,
|
||||||
|
imported: Int
|
||||||
|
) {
|
||||||
// - Imported keys number must be correct
|
// - Imported keys number must be correct
|
||||||
Assert.assertEquals(testData.aliceKeys.size, total)
|
Assert.assertEquals(testData.aliceKeys.size, total)
|
||||||
Assert.assertEquals(total, imported)
|
Assert.assertEquals(total, imported)
|
||||||
|
|
|
@ -18,5 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
||||||
|
|
||||||
data class PrepareKeysBackupDataResult(val megolmBackupCreationInfo: MegolmBackupCreationInfo,
|
data class PrepareKeysBackupDataResult(
|
||||||
val version: String)
|
val megolmBackupCreationInfo: MegolmBackupCreationInfo,
|
||||||
|
val version: String
|
||||||
|
)
|
||||||
|
|
|
@ -27,9 +27,11 @@ import java.util.concurrent.CountDownLatch
|
||||||
* This class observe the state change of a KeysBackup object and provide a method to check the several state change
|
* This class observe the state change of a KeysBackup object and provide a method to check the several state change
|
||||||
* It checks all state transitions and detected forbidden transition
|
* It checks all state transitions and detected forbidden transition
|
||||||
*/
|
*/
|
||||||
internal class StateObserver(private val keysBackup: KeysBackupService,
|
internal class StateObserver(
|
||||||
private val latch: CountDownLatch? = null,
|
private val keysBackup: KeysBackupService,
|
||||||
private val expectedStateChange: Int = -1) : KeysBackupStateListener {
|
private val latch: CountDownLatch? = null,
|
||||||
|
private val expectedStateChange: Int = -1
|
||||||
|
) : KeysBackupStateListener {
|
||||||
|
|
||||||
private val allowedStateTransitions = listOf(
|
private val allowedStateTransitions = listOf(
|
||||||
KeysBackupState.BackingUp to KeysBackupState.ReadyToBackUp,
|
KeysBackupState.BackingUp to KeysBackupState.ReadyToBackUp,
|
||||||
|
|
|
@ -52,6 +52,7 @@ import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Ignore
|
||||||
class SASTest : InstrumentedTest {
|
class SASTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -264,14 +265,16 @@ class SASTest : InstrumentedTest {
|
||||||
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fakeBobStart(bobSession: Session,
|
private fun fakeBobStart(
|
||||||
aliceUserID: String?,
|
bobSession: Session,
|
||||||
aliceDevice: String?,
|
aliceUserID: String?,
|
||||||
tid: String,
|
aliceDevice: String?,
|
||||||
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
|
tid: String,
|
||||||
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES,
|
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
|
||||||
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS,
|
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES,
|
||||||
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES) {
|
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS,
|
||||||
|
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES
|
||||||
|
) {
|
||||||
val startMessage = KeyVerificationStart(
|
val startMessage = KeyVerificationStart(
|
||||||
fromDevice = bobSession.cryptoService().getMyDevice().deviceId,
|
fromDevice = bobSession.cryptoService().getMyDevice().deviceId,
|
||||||
method = VerificationMethod.SAS.toValue(),
|
method = VerificationMethod.SAS.toValue(),
|
||||||
|
@ -412,7 +415,7 @@ class SASTest : InstrumentedTest {
|
||||||
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
||||||
aliceSASLatch.countDown()
|
aliceSASLatch.countDown()
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +429,7 @@ class SASTest : InstrumentedTest {
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
||||||
tx.performAccept()
|
tx.performAccept()
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
|
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
|
||||||
bobSASLatch.countDown()
|
bobSASLatch.countDown()
|
||||||
|
@ -476,7 +479,7 @@ class SASTest : InstrumentedTest {
|
||||||
aliceSASLatch.countDown()
|
aliceSASLatch.countDown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -496,16 +499,16 @@ class SASTest : InstrumentedTest {
|
||||||
tx.performAccept()
|
tx.performAccept()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
||||||
if (matchOnce) {
|
if (matchOnce) {
|
||||||
matchOnce = false
|
matchOnce = false
|
||||||
tx.userHasVerifiedShortCode()
|
tx.userHasVerifiedShortCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
||||||
bobSASLatch.countDown()
|
bobSASLatch.countDown()
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.amshove.kluent.shouldBe
|
import org.amshove.kluent.shouldBe
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
|
@ -41,6 +42,7 @@ import kotlin.coroutines.resume
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
@Ignore
|
||||||
class VerificationTest : InstrumentedTest {
|
class VerificationTest : InstrumentedTest {
|
||||||
|
|
||||||
data class ExpectedResult(
|
data class ExpectedResult(
|
||||||
|
@ -151,10 +153,12 @@ class VerificationTest : InstrumentedTest {
|
||||||
|
|
||||||
// TODO Add tests without SAS
|
// TODO Add tests without SAS
|
||||||
|
|
||||||
private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
|
private fun doTest(
|
||||||
bobSupportedMethods: List<VerificationMethod>,
|
aliceSupportedMethods: List<VerificationMethod>,
|
||||||
expectedResultForAlice: ExpectedResult,
|
bobSupportedMethods: List<VerificationMethod>,
|
||||||
expectedResultForBob: ExpectedResult) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
expectedResultForAlice: ExpectedResult,
|
||||||
|
expectedResultForBob: ExpectedResult
|
||||||
|
) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
|
|
|
@ -289,9 +289,11 @@ class MarkdownParserTest : InstrumentedTest {
|
||||||
markdownParser.parse(text).expect(text, null)
|
markdownParser.parse(text).expect(text, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testType(name: String,
|
private fun testType(
|
||||||
markdownPattern: String,
|
name: String,
|
||||||
htmlExpectedTag: String) {
|
markdownPattern: String,
|
||||||
|
htmlExpectedTag: String
|
||||||
|
) {
|
||||||
// Test simple case
|
// Test simple case
|
||||||
"$markdownPattern$name$markdownPattern"
|
"$markdownPattern$name$markdownPattern"
|
||||||
.let {
|
.let {
|
||||||
|
@ -376,10 +378,12 @@ class MarkdownParserTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testTypeNewLines(name: String,
|
private fun testTypeNewLines(
|
||||||
markdownPattern: String,
|
name: String,
|
||||||
htmlExpectedTag: String,
|
markdownPattern: String,
|
||||||
softBreak: String = "<br />") {
|
htmlExpectedTag: String,
|
||||||
|
softBreak: String = "<br />"
|
||||||
|
) {
|
||||||
// With new line inside the block
|
// With new line inside the block
|
||||||
"$markdownPattern$name\n$name$markdownPattern"
|
"$markdownPattern$name\n$name$markdownPattern"
|
||||||
.let {
|
.let {
|
||||||
|
|
|
@ -44,7 +44,7 @@ class TestPermalinkService : PermalinkService {
|
||||||
|
|
||||||
override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String {
|
override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
HTML -> "<a href=\"https://matrix.to/#/%1\$s\">%2\$s</a>"
|
HTML -> "<a href=\"https://matrix.to/#/%1\$s\">%2\$s</a>"
|
||||||
MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)"
|
MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
timeline.start()
|
timeline.start()
|
||||||
|
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
@ -97,7 +97,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
timeline.addListener(eventsListener)
|
timeline.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -144,7 +144,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
timeline.start()
|
timeline.start()
|
||||||
|
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
@ -156,9 +156,9 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
timeline.addListener(eventsListener)
|
timeline.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
|
|
||||||
bobSession.startSync(true)
|
bobSession.syncService().startSync(true)
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
@ -170,7 +170,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
timeline.addListener(eventsListener)
|
timeline.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
bobSession.stopSync()
|
bobSession.syncService().stopSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -217,7 +217,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
timeline.start()
|
timeline.start()
|
||||||
|
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
@ -233,7 +233,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
timeline.addListener(eventsListener)
|
timeline.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -314,7 +314,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
timeline.start()
|
timeline.start()
|
||||||
|
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
@ -338,6 +338,6 @@ class ThreadMessagingTest : InstrumentedTest {
|
||||||
timeline.addListener(eventsListener)
|
timeline.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,9 +154,11 @@ internal class ChunkEntityTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ChunkEntity.addAll(roomId: String,
|
private fun ChunkEntity.addAll(
|
||||||
events: List<Event>,
|
roomId: String,
|
||||||
direction: PaginationDirection) {
|
events: List<Event>,
|
||||||
|
direction: PaginationDirection
|
||||||
|
) {
|
||||||
events.forEach { event ->
|
events.forEach { event ->
|
||||||
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let {
|
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let {
|
||||||
realm.copyToRealm(it)
|
realm.copyToRealm(it)
|
||||||
|
|
|
@ -19,8 +19,9 @@ package org.matrix.android.sdk.session.room.timeline
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEvent
|
import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEvent
|
||||||
|
|
||||||
internal data class FakeTokenChunkEvent(override val start: String?,
|
internal data class FakeTokenChunkEvent(
|
||||||
override val end: String?,
|
override val start: String?,
|
||||||
override val events: List<Event> = emptyList(),
|
override val end: String?,
|
||||||
override val stateEvents: List<Event> = emptyList()
|
override val events: List<Event> = emptyList(),
|
||||||
|
override val stateEvents: List<Event> = emptyList()
|
||||||
) : TokenChunkEvent
|
) : TokenChunkEvent
|
||||||
|
|
|
@ -57,7 +57,7 @@ class PollAggregationTest : InstrumentedTest {
|
||||||
// Bob creates a poll
|
// Bob creates a poll
|
||||||
roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
|
roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
|
||||||
|
|
||||||
aliceSession.startSync(true)
|
aliceSession.syncService().startSync(true)
|
||||||
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
|
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
aliceTimeline.start()
|
aliceTimeline.start()
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class PollAggregationTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
when (lock.count.toInt()) {
|
when (lock.count.toInt()) {
|
||||||
TOTAL_TEST_COUNT -> {
|
TOTAL_TEST_COUNT -> {
|
||||||
// Poll has just been created.
|
// Poll has just been created.
|
||||||
testInitialPollConditions(pollContent, pollSummary)
|
testInitialPollConditions(pollContent, pollSummary)
|
||||||
lock.countDown()
|
lock.countDown()
|
||||||
|
@ -119,7 +119,7 @@ class PollAggregationTest : InstrumentedTest {
|
||||||
testEndedPoll(pollSummary)
|
testEndedPoll(pollSummary)
|
||||||
lock.countDown()
|
lock.countDown()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
fail("Lock count ${lock.count} didn't handled.")
|
fail("Lock count ${lock.count} didn't handled.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ class PollAggregationTest : InstrumentedTest {
|
||||||
|
|
||||||
aliceTimeline.removeAllListeners()
|
aliceTimeline.removeAllListeners()
|
||||||
|
|
||||||
aliceSession.stopSync()
|
aliceSession.syncService().stopSync()
|
||||||
aliceTimeline.dispose()
|
aliceTimeline.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,12 @@ object RoomDataHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFakeEvent(type: String,
|
private fun createFakeEvent(
|
||||||
content: Content? = null,
|
type: String,
|
||||||
prevContent: Content? = null,
|
content: Content? = null,
|
||||||
sender: String = FAKE_TEST_SENDER,
|
prevContent: Content? = null,
|
||||||
stateKey: String? = null
|
sender: String = FAKE_TEST_SENDER,
|
||||||
|
stateKey: String? = null
|
||||||
): Event {
|
): Event {
|
||||||
return Event(
|
return Event(
|
||||||
type = type,
|
type = type,
|
||||||
|
|
|
@ -88,7 +88,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bob stop to sync
|
// Bob stop to sync
|
||||||
bobSession.stopSync()
|
bobSession.syncService().stopSync()
|
||||||
|
|
||||||
val firstMessage = "First messages from Alice"
|
val firstMessage = "First messages from Alice"
|
||||||
// Alice sends 30 messages
|
// Alice sends 30 messages
|
||||||
|
@ -101,7 +101,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
||||||
.eventId
|
.eventId
|
||||||
|
|
||||||
// Bob start to sync
|
// Bob start to sync
|
||||||
bobSession.startSync(true)
|
bobSession.syncService().startSync(true)
|
||||||
|
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
@ -125,7 +125,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bob stop to sync
|
// Bob stop to sync
|
||||||
bobSession.stopSync()
|
bobSession.syncService().stopSync()
|
||||||
|
|
||||||
val secondMessage = "Second messages from Alice"
|
val secondMessage = "Second messages from Alice"
|
||||||
// Alice sends again 30 messages
|
// Alice sends again 30 messages
|
||||||
|
@ -136,7 +136,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bob start to sync
|
// Bob start to sync
|
||||||
bobSession.startSync(true)
|
bobSession.syncService().startSync(true)
|
||||||
|
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.test.filters.LargeTest
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.amshove.kluent.internal.assertEquals
|
import org.amshove.kluent.internal.assertEquals
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
|
@ -38,6 +39,7 @@ import org.matrix.android.sdk.common.TestConstants
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore
|
||||||
class TimelineSimpleBackPaginationTest : InstrumentedTest {
|
class TimelineSimpleBackPaginationTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -71,7 +71,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
|
||||||
val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30))
|
val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30))
|
||||||
timelineForCurrentMember.start()
|
timelineForCurrentMember.start()
|
||||||
|
|
||||||
session.startSync(true)
|
session.syncService().startSync(true)
|
||||||
|
|
||||||
run {
|
run {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
@ -92,7 +92,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
|
||||||
timelineForCurrentMember.addListener(eventsListener)
|
timelineForCurrentMember.addListener(eventsListener)
|
||||||
commonTestHelper.await(lock, 600_000)
|
commonTestHelper.await(lock, 600_000)
|
||||||
}
|
}
|
||||||
session.stopSync()
|
session.syncService().stopSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
|
@ -98,6 +99,7 @@ class SpaceCreationTest : InstrumentedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
|
fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
|
||||||
|
|
||||||
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
||||||
|
|
|
@ -387,9 +387,10 @@ class SpaceHierarchyTest : InstrumentedTest {
|
||||||
val roomIds: List<String>
|
val roomIds: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createPublicSpace(session: Session,
|
private fun createPublicSpace(
|
||||||
spaceName: String,
|
session: Session,
|
||||||
childInfo: List<Triple<String, Boolean, Boolean?>>
|
spaceName: String,
|
||||||
|
childInfo: List<Triple<String, Boolean, Boolean?>>
|
||||||
/** Name, auto-join, canonical*/
|
/** Name, auto-join, canonical*/
|
||||||
): TestSpaceCreationResult {
|
): TestSpaceCreationResult {
|
||||||
var spaceId = ""
|
var spaceId = ""
|
||||||
|
@ -416,9 +417,10 @@ class SpaceHierarchyTest : InstrumentedTest {
|
||||||
return TestSpaceCreationResult(spaceId, roomIds)
|
return TestSpaceCreationResult(spaceId, roomIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPrivateSpace(session: Session,
|
private fun createPrivateSpace(
|
||||||
spaceName: String,
|
session: Session,
|
||||||
childInfo: List<Triple<String, Boolean, Boolean?>>
|
spaceName: String,
|
||||||
|
childInfo: List<Triple<String, Boolean, Boolean?>>
|
||||||
/** Name, auto-join, canonical*/
|
/** Name, auto-join, canonical*/
|
||||||
): TestSpaceCreationResult {
|
): TestSpaceCreationResult {
|
||||||
var spaceId = ""
|
var spaceId = ""
|
||||||
|
|
|
@ -26,14 +26,14 @@ internal class InlineMaths(private val delimiter: InlineDelimiter) : CustomNode(
|
||||||
|
|
||||||
override fun getOpeningDelimiter(): String {
|
override fun getOpeningDelimiter(): String {
|
||||||
return when (delimiter) {
|
return when (delimiter) {
|
||||||
InlineDelimiter.SINGLE_DOLLAR -> "$"
|
InlineDelimiter.SINGLE_DOLLAR -> "$"
|
||||||
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\("
|
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\("
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getClosingDelimiter(): String {
|
override fun getClosingDelimiter(): String {
|
||||||
return when (delimiter) {
|
return when (delimiter) {
|
||||||
InlineDelimiter.SINGLE_DOLLAR -> "$"
|
InlineDelimiter.SINGLE_DOLLAR -> "$"
|
||||||
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\)"
|
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,11 @@ import org.matrix.android.sdk.api.session.Session
|
||||||
* This interface defines methods to authenticate or to create an account to a matrix server.
|
* This interface defines methods to authenticate or to create an account to a matrix server.
|
||||||
*/
|
*/
|
||||||
interface AuthenticationService {
|
interface AuthenticationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the supported login flows for this homeserver.
|
* Request the supported login flows for this homeserver.
|
||||||
* This is the first method to call to be able to get a wizard to login or to create an account
|
* This is the first method to call to be able to get a wizard to login or to create an account.
|
||||||
|
* @param homeServerConnectionConfig contains the homeserver URL to login to, a wellKnown lookup will be attempted.
|
||||||
*/
|
*/
|
||||||
suspend fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult
|
suspend fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult
|
||||||
|
|
||||||
|
@ -93,14 +95,18 @@ interface AuthenticationService {
|
||||||
/**
|
/**
|
||||||
* Create a session after a SSO successful login.
|
* Create a session after a SSO successful login.
|
||||||
*/
|
*/
|
||||||
suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
|
suspend fun createSessionFromSso(
|
||||||
credentials: Credentials): Session
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
credentials: Credentials
|
||||||
|
): Session
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a wellknown request, using the domain from the matrixId.
|
* Perform a wellknown request, using the domain from the matrixId.
|
||||||
*/
|
*/
|
||||||
suspend fun getWellKnownData(matrixId: String,
|
suspend fun getWellKnownData(
|
||||||
homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult
|
matrixId: String,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig?
|
||||||
|
): WellknownResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate with a matrixId and a password.
|
* Authenticate with a matrixId and a password.
|
||||||
|
@ -111,9 +117,11 @@ interface AuthenticationService {
|
||||||
* @param initialDeviceName the initial device name
|
* @param initialDeviceName the initial device name
|
||||||
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
|
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
|
||||||
*/
|
*/
|
||||||
suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
|
suspend fun directAuthentication(
|
||||||
matrixId: String,
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
password: String,
|
matrixId: String,
|
||||||
initialDeviceName: String,
|
password: String,
|
||||||
deviceId: String? = null): Session
|
initialDeviceName: String,
|
||||||
|
deviceId: String? = null
|
||||||
|
): Session
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,10 @@ import org.matrix.android.sdk.api.auth.registration.TermPolicies
|
||||||
* @param userLanguage the user language
|
* @param userLanguage the user language
|
||||||
* @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse
|
* @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse
|
||||||
*/
|
*/
|
||||||
fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
|
fun TermPolicies.toLocalizedLoginTerms(
|
||||||
defaultLanguage: String = "en"): List<LocalizedFlowDataLoginTerms> {
|
userLanguage: String,
|
||||||
|
defaultLanguage: String = "en"
|
||||||
|
): List<LocalizedFlowDataLoginTerms> {
|
||||||
val result = ArrayList<LocalizedFlowDataLoginTerms>()
|
val result = ArrayList<LocalizedFlowDataLoginTerms>()
|
||||||
|
|
||||||
val policies = get("policies")
|
val policies = get("policies")
|
||||||
|
@ -67,8 +69,8 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
|
||||||
// Search for language
|
// Search for language
|
||||||
policy.keys.forEach { policyKey ->
|
policy.keys.forEach { policyKey ->
|
||||||
when (policyKey) {
|
when (policyKey) {
|
||||||
"version" -> Unit // Ignore
|
"version" -> Unit // Ignore
|
||||||
userLanguage -> {
|
userLanguage -> {
|
||||||
// We found the data for the user language
|
// We found the data for the user language
|
||||||
userLanguageUrlAndName = extractUrlAndName(policy[policyKey])
|
userLanguageUrlAndName = extractUrlAndName(policy[policyKey])
|
||||||
}
|
}
|
||||||
|
@ -76,7 +78,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
|
||||||
// We found default language
|
// We found default language
|
||||||
defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey])
|
defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey])
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (firstUrlAndName == null) {
|
if (firstUrlAndName == null) {
|
||||||
// Get at least some data
|
// Get at least some data
|
||||||
firstUrlAndName = extractUrlAndName(policy[policyKey])
|
firstUrlAndName = extractUrlAndName(policy[policyKey])
|
||||||
|
@ -87,7 +89,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
|
||||||
|
|
||||||
// Copy found language data by priority
|
// Copy found language data by priority
|
||||||
when {
|
when {
|
||||||
userLanguageUrlAndName != null -> {
|
userLanguageUrlAndName != null -> {
|
||||||
localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url
|
localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url
|
||||||
localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name
|
localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name
|
||||||
}
|
}
|
||||||
|
@ -95,7 +97,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
|
||||||
localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url
|
localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url
|
||||||
localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name
|
localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name
|
||||||
}
|
}
|
||||||
firstUrlAndName != null -> {
|
firstUrlAndName != null -> {
|
||||||
localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url
|
localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url
|
||||||
localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name
|
localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,17 +66,17 @@ data class SsoIdentityProvider(
|
||||||
private fun toPriority(): Int {
|
private fun toPriority(): Int {
|
||||||
return when (brand) {
|
return when (brand) {
|
||||||
// We are on Android, so user is more likely to have a Google account
|
// We are on Android, so user is more likely to have a Google account
|
||||||
BRAND_GOOGLE -> 5
|
BRAND_GOOGLE -> 5
|
||||||
// Facebook is also an important SSO provider
|
// Facebook is also an important SSO provider
|
||||||
BRAND_FACEBOOK -> 4
|
BRAND_FACEBOOK -> 4
|
||||||
// Twitter is more for professionals
|
// Twitter is more for professionals
|
||||||
BRAND_TWITTER -> 3
|
BRAND_TWITTER -> 3
|
||||||
// Here it's very for techie people
|
// Here it's very for techie people
|
||||||
BRAND_GITHUB,
|
BRAND_GITHUB,
|
||||||
BRAND_GITLAB -> 2
|
BRAND_GITLAB -> 2
|
||||||
// And finally, if the account has been created with an iPhone...
|
// And finally, if the account has been created with an iPhone...
|
||||||
BRAND_APPLE -> 1
|
BRAND_APPLE -> 1
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,12 @@ interface LoginWizard {
|
||||||
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
|
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
|
||||||
* @return a [Session] if the login is successful
|
* @return a [Session] if the login is successful
|
||||||
*/
|
*/
|
||||||
suspend fun login(login: String,
|
suspend fun login(
|
||||||
password: String,
|
login: String,
|
||||||
initialDeviceName: String,
|
password: String,
|
||||||
deviceId: String? = null): Session
|
initialDeviceName: String,
|
||||||
|
deviceId: String? = null
|
||||||
|
): Session
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchange a login token to an access token.
|
* Exchange a login token to an access token.
|
||||||
|
@ -63,14 +65,14 @@ interface LoginWizard {
|
||||||
* [resetPasswordMailConfirmed] is successfully called.
|
* [resetPasswordMailConfirmed] is successfully called.
|
||||||
*
|
*
|
||||||
* @param email an email previously associated to the account the user wants the password to be reset.
|
* @param email an email previously associated to the account the user wants the password to be reset.
|
||||||
* @param newPassword the desired new password
|
|
||||||
*/
|
*/
|
||||||
suspend fun resetPassword(email: String,
|
suspend fun resetPassword(email: String)
|
||||||
newPassword: String)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirm the new password, once the user has checked their email
|
* Confirm the new password, once the user has checked their email
|
||||||
* When this method succeed, tha account password will be effectively modified.
|
* When this method succeed, tha account password will be effectively modified.
|
||||||
|
*
|
||||||
|
* @param newPassword the desired new password
|
||||||
*/
|
*/
|
||||||
suspend fun resetPasswordMailConfirmed()
|
suspend fun resetPasswordMailConfirmed(newPassword: String)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,15 +88,15 @@ fun RegistrationFlowResponse.toFlowResult(): FlowResult {
|
||||||
val isMandatory = flows?.all { type in it.stages.orEmpty() } == true
|
val isMandatory = flows?.all { type in it.stages.orEmpty() } == true
|
||||||
|
|
||||||
val stage = when (type) {
|
val stage = when (type) {
|
||||||
LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
|
LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
|
||||||
isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String)
|
isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String)
|
||||||
?: ""
|
?: ""
|
||||||
)
|
)
|
||||||
LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
|
LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
|
||||||
LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap<String, String>())
|
LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap<String, String>())
|
||||||
LoginFlowTypes.EMAIL_IDENTITY -> Stage.Email(isMandatory)
|
LoginFlowTypes.EMAIL_IDENTITY -> Stage.Email(isMandatory)
|
||||||
LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
|
LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
|
||||||
else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
|
else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type in completedStages.orEmpty()) {
|
if (type in completedStages.orEmpty()) {
|
||||||
|
|
|
@ -54,9 +54,11 @@ interface RegistrationWizard {
|
||||||
* @param password the desired password
|
* @param password the desired password
|
||||||
* @param initialDeviceDisplayName the device display name
|
* @param initialDeviceDisplayName the device display name
|
||||||
*/
|
*/
|
||||||
suspend fun createAccount(userName: String?,
|
suspend fun createAccount(
|
||||||
password: String?,
|
userName: String?,
|
||||||
initialDeviceDisplayName: String?): RegistrationResult
|
password: String?,
|
||||||
|
initialDeviceDisplayName: String?
|
||||||
|
): RegistrationResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the "m.login.recaptcha" stage.
|
* Perform the "m.login.recaptcha" stage.
|
||||||
|
|
|
@ -26,9 +26,11 @@ sealed class WellknownResult {
|
||||||
* Retrieve the specific piece of information from the user in a way which fits within the existing client user experience,
|
* Retrieve the specific piece of information from the user in a way which fits within the existing client user experience,
|
||||||
* if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.
|
* if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.
|
||||||
*/
|
*/
|
||||||
data class Prompt(val homeServerUrl: String,
|
data class Prompt(
|
||||||
val identityServerUrl: String?,
|
val homeServerUrl: String,
|
||||||
val wellKnown: WellKnown) : WellknownResult()
|
val identityServerUrl: String?,
|
||||||
|
val wellKnown: WellKnown
|
||||||
|
) : WellknownResult()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the current auto-discovery mechanism. If no more auto-discovery mechanisms are available,
|
* Stop the current auto-discovery mechanism. If no more auto-discovery mechanisms are available,
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.extensions
|
||||||
fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
||||||
return when {
|
return when {
|
||||||
startsWith(prefix) -> this
|
startsWith(prefix) -> this
|
||||||
else -> "$prefix$this"
|
else -> "$prefix$this"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,3 +27,8 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
||||||
* Append a new line and then the provided string.
|
* Append a new line and then the provided string.
|
||||||
*/
|
*/
|
||||||
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
|
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns null if the string is empty.
|
||||||
|
*/
|
||||||
|
fun String.ensureNotEmpty() = ifEmpty { null }
|
||||||
|
|
|
@ -36,7 +36,7 @@ data class Fingerprint(
|
||||||
internal fun matchesCert(cert: X509Certificate): Boolean {
|
internal fun matchesCert(cert: X509Certificate): Boolean {
|
||||||
val o: Fingerprint? = when (hashType) {
|
val o: Fingerprint? = when (hashType) {
|
||||||
HashType.SHA256 -> newSha256Fingerprint(cert)
|
HashType.SHA256 -> newSha256Fingerprint(cert)
|
||||||
HashType.SHA1 -> newSha1Fingerprint(cert)
|
HashType.SHA1 -> newSha1Fingerprint(cert)
|
||||||
}
|
}
|
||||||
return equals(o)
|
return equals(o)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
package org.matrix.android.sdk.api.session
|
package org.matrix.android.sdk.api.session
|
||||||
|
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||||
|
@ -37,7 +35,6 @@ import org.matrix.android.sdk.api.session.file.FileService
|
||||||
import org.matrix.android.sdk.api.session.group.GroupService
|
import org.matrix.android.sdk.api.session.group.GroupService
|
||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
import org.matrix.android.sdk.api.session.identity.IdentityService
|
import org.matrix.android.sdk.api.session.identity.IdentityService
|
||||||
import org.matrix.android.sdk.api.session.initsync.SyncStatusService
|
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.session.media.MediaService
|
import org.matrix.android.sdk.api.session.media.MediaService
|
||||||
import org.matrix.android.sdk.api.session.openid.OpenIdService
|
import org.matrix.android.sdk.api.session.openid.OpenIdService
|
||||||
|
@ -55,8 +52,7 @@ import org.matrix.android.sdk.api.session.signout.SignOutService
|
||||||
import org.matrix.android.sdk.api.session.space.SpaceService
|
import org.matrix.android.sdk.api.session.space.SpaceService
|
||||||
import org.matrix.android.sdk.api.session.statistics.StatisticsListener
|
import org.matrix.android.sdk.api.session.statistics.StatisticsListener
|
||||||
import org.matrix.android.sdk.api.session.sync.FilterService
|
import org.matrix.android.sdk.api.session.sync.FilterService
|
||||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
import org.matrix.android.sdk.api.session.sync.SyncService
|
||||||
import org.matrix.android.sdk.api.session.sync.model.SyncResponse
|
|
||||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||||
import org.matrix.android.sdk.api.session.thirdparty.ThirdPartyService
|
import org.matrix.android.sdk.api.session.thirdparty.ThirdPartyService
|
||||||
import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
|
import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
|
||||||
|
@ -98,59 +94,11 @@ interface Session {
|
||||||
@MainThread
|
@MainThread
|
||||||
fun open()
|
fun open()
|
||||||
|
|
||||||
/**
|
|
||||||
* Requires a one time background sync.
|
|
||||||
*/
|
|
||||||
fun requireBackgroundSync()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launches infinite self rescheduling background syncs via the WorkManager.
|
|
||||||
*
|
|
||||||
* While dozing, syncs will only occur during maintenance windows.
|
|
||||||
* For reliability it's recommended to also start a long running foreground service
|
|
||||||
* along with disabling battery optimizations.
|
|
||||||
*/
|
|
||||||
fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long)
|
|
||||||
|
|
||||||
fun stopAnyBackgroundSync()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method start the sync thread.
|
|
||||||
*/
|
|
||||||
fun startSync(fromForeground: Boolean)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method stop the sync thread.
|
|
||||||
*/
|
|
||||||
fun stopSync()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear cache of the session.
|
* Clear cache of the session.
|
||||||
*/
|
*/
|
||||||
suspend fun clearCache()
|
suspend fun clearCache()
|
||||||
|
|
||||||
/**
|
|
||||||
* This method allows to listen the sync state.
|
|
||||||
* @return a [LiveData] of [SyncState].
|
|
||||||
*/
|
|
||||||
fun getSyncStateLive(): LiveData<SyncState>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the current sync state.
|
|
||||||
* @return the current [SyncState].
|
|
||||||
*/
|
|
||||||
fun getSyncState(): SyncState
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns a flow of SyncResponse. New value will be pushed through the sync thread.
|
|
||||||
*/
|
|
||||||
fun syncFlow(): SharedFlow<SyncResponse>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This methods return true if an initial sync has been processed.
|
|
||||||
*/
|
|
||||||
fun hasAlreadySynced(): Boolean
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method allow to close a session. It does stop some services.
|
* This method allow to close a session. It does stop some services.
|
||||||
*/
|
*/
|
||||||
|
@ -247,9 +195,9 @@ interface Session {
|
||||||
fun termsService(): TermsService
|
fun termsService(): TermsService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SyncStatusService associated with the session.
|
* Returns the SyncService associated with the session.
|
||||||
*/
|
*/
|
||||||
fun syncStatusService(): SyncStatusService
|
fun syncService(): SyncService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SecureStorageService associated with the session.
|
* Returns the SecureStorageService associated with the session.
|
||||||
|
|
|
@ -27,8 +27,10 @@ interface AccountService {
|
||||||
* @param password Current password.
|
* @param password Current password.
|
||||||
* @param newPassword New password
|
* @param newPassword New password
|
||||||
*/
|
*/
|
||||||
suspend fun changePassword(password: String,
|
suspend fun changePassword(
|
||||||
newPassword: String)
|
password: String,
|
||||||
|
newPassword: String
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate the account.
|
* Deactivate the account.
|
||||||
|
@ -46,6 +48,8 @@ interface AccountService {
|
||||||
* an incomplete view of conversations
|
* an incomplete view of conversations
|
||||||
* @param userInteractiveAuthInterceptor see [UserInteractiveAuthInterceptor]
|
* @param userInteractiveAuthInterceptor see [UserInteractiveAuthInterceptor]
|
||||||
*/
|
*/
|
||||||
suspend fun deactivateAccount(eraseAllData: Boolean,
|
suspend fun deactivateAccount(
|
||||||
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
|
eraseAllData: Boolean,
|
||||||
|
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,10 +91,12 @@ interface MxCall : MxCallDetail {
|
||||||
* Send a m.call.replaces event to initiate call transfer.
|
* Send a m.call.replaces event to initiate call transfer.
|
||||||
* See [org.matrix.android.sdk.api.session.room.model.call.CallReplacesContent] for documentation about the parameters
|
* See [org.matrix.android.sdk.api.session.room.model.call.CallReplacesContent] for documentation about the parameters
|
||||||
*/
|
*/
|
||||||
suspend fun transfer(targetUserId: String,
|
suspend fun transfer(
|
||||||
targetRoomId: String?,
|
targetUserId: String,
|
||||||
createCallId: String?,
|
targetRoomId: String?,
|
||||||
awaitCallId: String?)
|
createCallId: String?,
|
||||||
|
awaitCallId: String?
|
||||||
|
)
|
||||||
|
|
||||||
fun addListener(listener: StateListener)
|
fun addListener(listener: StateListener)
|
||||||
fun removeListener(listener: StateListener)
|
fun removeListener(listener: StateListener)
|
||||||
|
|
|
@ -88,9 +88,11 @@ interface CryptoService {
|
||||||
|
|
||||||
fun getDeviceTrackingStatus(userId: String): Int
|
fun getDeviceTrackingStatus(userId: String): Int
|
||||||
|
|
||||||
suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
|
suspend fun importRoomKeys(
|
||||||
password: String,
|
roomKeysAsArray: ByteArray,
|
||||||
progressListener: ProgressListener?): ImportRoomKeysResult
|
password: String,
|
||||||
|
progressListener: ProgressListener?
|
||||||
|
): ImportRoomKeysResult
|
||||||
|
|
||||||
suspend fun exportRoomKeys(password: String): ByteArray
|
suspend fun exportRoomKeys(password: String): ByteArray
|
||||||
|
|
||||||
|
@ -119,10 +121,12 @@ interface CryptoService {
|
||||||
fun isRoomEncrypted(roomId: String): Boolean
|
fun isRoomEncrypted(roomId: String): Boolean
|
||||||
|
|
||||||
// TODO This could be removed from this interface
|
// TODO This could be removed from this interface
|
||||||
fun encryptEventContent(eventContent: Content,
|
fun encryptEventContent(
|
||||||
eventType: String,
|
eventContent: Content,
|
||||||
roomId: String,
|
eventType: String,
|
||||||
callback: MatrixCallback<MXEncryptEventContentResult>)
|
roomId: String,
|
||||||
|
callback: MatrixCallback<MXEncryptEventContentResult>
|
||||||
|
)
|
||||||
|
|
||||||
fun discardOutboundSession(roomId: String)
|
fun discardOutboundSession(roomId: String)
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,14 @@ import org.matrix.olm.OlmException
|
||||||
*/
|
*/
|
||||||
sealed class MXCryptoError : Throwable() {
|
sealed class MXCryptoError : Throwable() {
|
||||||
|
|
||||||
data class Base(val errorType: ErrorType,
|
data class Base(
|
||||||
val technicalMessage: String,
|
val errorType: ErrorType,
|
||||||
/**
|
val technicalMessage: String,
|
||||||
* Describe the error with more details.
|
/**
|
||||||
*/
|
* Describe the error with more details.
|
||||||
val detailedErrorDescription: String? = null) : MXCryptoError()
|
*/
|
||||||
|
val detailedErrorDescription: String? = null
|
||||||
|
) : MXCryptoError()
|
||||||
|
|
||||||
data class OlmError(val olmException: OlmException) : MXCryptoError()
|
data class OlmError(val olmException: OlmException) : MXCryptoError()
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ data class RequestReply(
|
||||||
)
|
)
|
||||||
|
|
||||||
sealed class RequestResult {
|
sealed class RequestResult {
|
||||||
data class Success(val chainIndex: Int) : RequestResult()
|
data class Success(val chainIndex: Int) : RequestResult()
|
||||||
data class Failure(val code: WithHeldCode) : RequestResult()
|
data class Failure(val code: WithHeldCode) : RequestResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,18 @@ interface CrossSigningService {
|
||||||
* Initialize cross signing for this user.
|
* Initialize cross signing for this user.
|
||||||
* Users needs to enter credentials
|
* Users needs to enter credentials
|
||||||
*/
|
*/
|
||||||
fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?,
|
fun initializeCrossSigning(
|
||||||
callback: MatrixCallback<Unit>)
|
uiaInterceptor: UserInteractiveAuthInterceptor?,
|
||||||
|
callback: MatrixCallback<Unit>
|
||||||
|
)
|
||||||
|
|
||||||
fun isCrossSigningInitialized(): Boolean = getMyCrossSigningKeys() != null
|
fun isCrossSigningInitialized(): Boolean = getMyCrossSigningKeys() != null
|
||||||
|
|
||||||
fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
|
fun checkTrustFromPrivateKeys(
|
||||||
uskKeyPrivateKey: String?,
|
masterKeyPrivateKey: String?,
|
||||||
sskPrivateKey: String?): UserTrustResult
|
uskKeyPrivateKey: String?,
|
||||||
|
sskPrivateKey: String?
|
||||||
|
): UserTrustResult
|
||||||
|
|
||||||
fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo?
|
fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo?
|
||||||
|
|
||||||
|
@ -60,20 +64,26 @@ interface CrossSigningService {
|
||||||
|
|
||||||
fun allPrivateKeysKnown(): Boolean
|
fun allPrivateKeysKnown(): Boolean
|
||||||
|
|
||||||
fun trustUser(otherUserId: String,
|
fun trustUser(
|
||||||
callback: MatrixCallback<Unit>)
|
otherUserId: String,
|
||||||
|
callback: MatrixCallback<Unit>
|
||||||
|
)
|
||||||
|
|
||||||
fun markMyMasterKeyAsTrusted()
|
fun markMyMasterKeyAsTrusted()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign one of your devices and upload the signature.
|
* Sign one of your devices and upload the signature.
|
||||||
*/
|
*/
|
||||||
fun trustDevice(deviceId: String,
|
fun trustDevice(
|
||||||
callback: MatrixCallback<Unit>)
|
deviceId: String,
|
||||||
|
callback: MatrixCallback<Unit>
|
||||||
|
)
|
||||||
|
|
||||||
fun checkDeviceTrust(otherUserId: String,
|
fun checkDeviceTrust(
|
||||||
otherDeviceId: String,
|
otherUserId: String,
|
||||||
locallyTrusted: Boolean?): DeviceTrustResult
|
otherDeviceId: String,
|
||||||
|
locallyTrusted: Boolean?
|
||||||
|
): DeviceTrustResult
|
||||||
|
|
||||||
// FIXME Those method do not have to be in the service
|
// FIXME Those method do not have to be in the service
|
||||||
fun onSecretMSKGossip(mskPrivateKey: String)
|
fun onSecretMSKGossip(mskPrivateKey: String)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue