Merge branch 'release/v1.4.22'

This commit is contained in:
Adam Brown 2022-06-14 15:13:14 +01:00
commit 3390e206b0
1108 changed files with 11082 additions and 8490 deletions

View file

@ -764,7 +764,7 @@ ij_groovy_while_on_new_line = false
ij_groovy_wrap_long_lines = false
[{*.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_extends_list = 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_method_annotation_wrap = split_into_lines
ij_kotlin_method_call_chain_wrap = off
ij_kotlin_method_parameters_new_line_after_left_paren = false
ij_kotlin_method_parameters_right_paren_on_new_line = false
ij_kotlin_method_parameters_new_line_after_left_paren = true
ij_kotlin_method_parameters_right_paren_on_new_line = true
ij_kotlin_method_parameters_wrap = off
ij_kotlin_name_count_to_use_star_import = 2147483647
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647

View file

@ -73,3 +73,14 @@ body:
- 'No'
validations:
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

View file

@ -34,3 +34,14 @@ body:
placeholder: Is there anything else you'd like to add?
validations:
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

View file

@ -49,24 +49,34 @@ body:
### 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
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
- [ ] Push to beta release to 100% of the users
- [ ] Notify the F-Droid team so that they can schedule the publication on F-Droid
- [ ] Push the open testing release to 100% of the users
- [ ] 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
- [ ] 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 crash reports on the GooglePlay console
- [ ] Check the Android Element room for any reported issues on the new version
- [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
- [ ] Ping the Android public room and update its topic with the new available version
- [ ] 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.
- [ ] 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

View file

@ -29,200 +29,6 @@ jobs:
steps:
- 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:
name: UI Tests (Synapse)
needs: should-i-run
@ -282,42 +88,13 @@ jobs:
emulator.log
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:
name: Notify matrix
runs-on: ubuntu-latest
needs:
- should-i-run
- integration-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'))
# No concurrency required, runs every time on a schedule.
steps:

View file

@ -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}}"

View file

@ -12,73 +12,100 @@ env:
-Porg.gradle.parallel=false
jobs:
# Build Android Tests
build-android-tests:
name: Build Android Tests
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
tests:
name: Runs all tests
runs-on: macos-latest # for the emulator
# Allow all jobs on main and develop. Just one per PR.
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) }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Run unit tests
run: ./gradlew clean test $CI_GRADLE_ARG_PROPERTIES --stacktrace
fetch-depth: 0
- uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '11'
- uses: gradle/gradle-build-action@v2
- uses: actions/setup-python@v3
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
if: always()
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.
notify:
runs-on: ubuntu-latest
needs:
- unit-tests
- build-android-tests
if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' ) && failure() }}
steps:
- uses: michaelkaye/matrix-hookshot-action@v0.3.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }}
matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }}
text_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}{{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
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}}"
# can't be run on macos due to containers.
# - 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
# Unneeded as part of the test suite above, kept around in case we want to re-enable them.
#
# # Build Android Tests
# build-android-tests:
# name: Build Android Tests
# 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

View file

@ -9,15 +9,15 @@ jobs:
name: Add Z-Labs label for features behind labs flags
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
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-Tags')
contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
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-Tags')
steps:
- uses: actions/github-script@v5
with:
@ -79,7 +79,7 @@ jobs:
name: X-Needs-Product to Design project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
@ -105,10 +105,7 @@ jobs:
# Skip in forks
if: >
github.repository == 'vector-im/element-android' &&
(contains(github.event.issue.labels.*.name, 'A-Spaces') ||
contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
contains(github.event.issue.labels.*.name, 'A-Subspaces') ||
contains(github.event.issue.labels.*.name, 'Z-IA'))
(contains(github.event.issue.labels.*.name, 'Team: Delight'))
steps:
- uses: octokit/graphql-action@v2.x
with:

View file

@ -14,10 +14,7 @@ jobs:
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
!contains(github.event.issue.labels.*.name, 'A-Spaces') &&
!contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
!contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||

View file

@ -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)
======================================

View file

@ -1,9 +1,9 @@
[![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)
[![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)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=im.vector.app.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)
[![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=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=vector-im_element-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
# Element Android

View file

@ -25,7 +25,7 @@ buildscript {
classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin
classpath 'com.google.gms:google-services:4.3.10'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
classpath "com.likethesalad.android:stem-plugin:2.1.1"
classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
@ -43,7 +43,7 @@ plugins {
id "io.gitlab.arturbosch.detekt" version "1.20.0"
// 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
@ -180,8 +180,8 @@ apply plugin: 'org.sonarqube'
sonarqube {
properties {
property "sonar.projectName", "Element-Android"
property "sonar.projectKey", "im.vector.app.android"
property "sonar.projectName", "element-android"
property "sonar.projectKey", "vector-im_element-android"
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
property "sonar.sourceEncoding", "UTF-8"
@ -191,7 +191,7 @@ sonarqube {
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
property "sonar.organization", "new_vector_ltd_organization"
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"
}
}

View file

@ -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) {
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 {
xml.enabled true
@ -18,11 +43,13 @@ def initializeReport(report, projects, classExcludes) {
switch (project) {
case { project.plugins.hasPlugin("com.android.application") }:
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/java")
break
case { project.plugins.hasPlugin("com.android.library") }:
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/java")
break
@ -43,13 +70,18 @@ def collectProjects(predicate) {
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
}
task allCodeCoverageReport(type: JacocoReport) {
task theCodeCoverageReport(type: JacocoReport) {
outputs.upToDateWhen { false }
rootProject.apply plugin: 'jacoco'
// to limit projects in a specific report, add
// def excludedProjects = [ ... ]
// def projects = collectProjects { !excludedProjects.contains(it.name) }
def projects = collectProjects { true }
dependsOn { projects*.test }
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
def projects = collectProjects { ['vector','matrix-sdk-android'].contains(it.name) }
dependsOn {
[':vector:testGplayDebugUnitTest'] +
[':vector:connectedGplayDebugAndroidTest'] +
[':matrix-sdk-android:testDebugUnitTest'] +
[':matrix-sdk-android:connectedDebugAndroidTest']
}
initializeReport(it, projects, excludes)
}

View file

@ -49,8 +49,8 @@ ext.libs = [
],
androidx : [
'activity' : "androidx.activity:activity:1.4.0",
'appCompat' : "androidx.appcompat:appcompat:1.4.1",
'core' : "androidx.core:core-ktx:1.7.0",
'appCompat' : "androidx.appcompat:appcompat:1.4.2",
'core' : "androidx.core:core-ktx:1.8.0",
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1",
@ -78,7 +78,7 @@ ext.libs = [
'transition' : "androidx.transition:transition:1.2.0",
],
google : [
'material' : "com.google.android.material:material:1.6.0"
'material' : "com.google.android.material:material:1.6.1"
],
dagger : [
'dagger' : "com.google.dagger:dagger:$dagger",

View file

@ -1,64 +1,49 @@
fastlane documentation
----
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```sh
```
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
## Android
### android test
```sh
[bundle exec] fastlane android test
```
fastlane android test
```
Runs all the tests
### android beta
```sh
[bundle exec] fastlane android beta
```
fastlane android beta
```
Submit a new Beta Build to Crashlytics Beta
### android deploy
```sh
[bundle exec] fastlane android deploy
```
fastlane android deploy
```
Deploy a new version to the Google Play
### android deployMeta
```sh
[bundle exec] fastlane android deployMeta
```
fastlane android deployMeta
```
Deploy Google Play metadata
### android getVersionCode
```sh
[bundle exec] fastlane android getVersionCode
```
fastlane android getVersionCode
```
Get version code
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
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).

View 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

View file

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

View file

@ -0,0 +1,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

View file

@ -0,0 +1,2 @@
تغییرات عمده در این نگارش: مدیریت بهتر پیام‌های رمزگذاشته. رفع اشکال‌های مختلف و بهبودهای پایداری.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Meilleure gestion des messages chiffrés. Plusieurs corrections de bogues et daméliorations de stabilité.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View 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

View 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

View file

@ -1 +1 @@
אלמנט (בעבר Riot.im)
אלמנט - התכתבות מאובטחת

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Поліпшено керування зашифрованими повідомленнями. Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:對於被加密的訊息有更好的管理方式。多個臭蟲修復與穩定性改善。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -271,7 +271,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
directionDetector.handleTouchEvent(event)
return when (swipeDirection) {
SwipeDirection.Up, SwipeDirection.Down -> {
SwipeDirection.Up, SwipeDirection.Down -> {
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
swipeDismissHandler.onTouch(views.rootContainer, event)
} else true
@ -279,7 +279,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
SwipeDirection.Left, SwipeDirection.Right -> {
views.attachmentPager.dispatchTouchEvent(event)
}
else -> true
else -> true
}
}

View file

@ -42,18 +42,18 @@ class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(viewType, parent, false)
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_video_attachment -> VideoViewHolder(itemView)
else -> UnsupportedViewHolder(itemView)
R.layout.item_video_attachment -> VideoViewHolder(itemView)
else -> UnsupportedViewHolder(itemView)
}
}
override fun getItemViewType(position: Int): Int {
val info = attachmentSourceProvider!!.getAttachmentInfoAt(position)
return when (info) {
is AttachmentInfo.Image -> R.layout.item_image_attachment
is AttachmentInfo.Video -> R.layout.item_video_attachment
is AttachmentInfo.Image -> R.layout.item_image_attachment
is AttachmentInfo.Video -> R.layout.item_video_attachment
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
// is AttachmentInfo.Audio -> TODO()
// is AttachmentInfo.File -> TODO()
@ -68,13 +68,13 @@ class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
holder.bind(it)
when (it) {
is AttachmentInfo.Image -> {
is AttachmentInfo.Image -> {
attachmentSourceProvider?.loadImage((holder as ZoomableImageViewHolder).target, it)
}
is AttachmentInfo.AnimatedImage -> {
attachmentSourceProvider?.loadImage((holder as AnimatedImageViewHolder).target, it)
}
is AttachmentInfo.Video -> {
is AttachmentInfo.Video -> {
attachmentSourceProvider?.loadVideo((holder as VideoViewHolder).target, it)
}
// else -> {

View file

@ -27,12 +27,12 @@ sealed class SwipeDirection {
companion object {
fun fromAngle(angle: Double): SwipeDirection {
return when (angle) {
in 0.0..45.0 -> Right
in 45.0..135.0 -> Up
in 0.0..45.0 -> Right
in 45.0..135.0 -> Up
in 135.0..225.0 -> Left
in 225.0..315.0 -> Down
in 315.0..360.0 -> Right
else -> NotDetected
else -> NotDetected
}
}
}

View file

@ -33,7 +33,7 @@ class SwipeDirectionDetector(
fun handleTouchEvent(event: MotionEvent) {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
MotionEvent.ACTION_DOWN -> {
startX = event.x
startY = event.y
}
@ -45,7 +45,7 @@ class SwipeDirectionDetector(
startX = startY
isDetected = false
}
MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
isDetected = true
onDirectionDetected(getDirection(startX, startY, event.x, event.y))
}

View file

@ -44,7 +44,7 @@ class SwipeToDismissHandler(
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
MotionEvent.ACTION_DOWN -> {
if (swipeView.hitRect.contains(event.x.toInt(), event.y.toInt())) {
isTracking = true
}
@ -58,7 +58,7 @@ class SwipeToDismissHandler(
}
return true
}
MotionEvent.ACTION_MOVE -> {
MotionEvent.ACTION_MOVE -> {
if (isTracking) {
val translationY = event.y - startY
swipeView.translationY = translationY
@ -66,7 +66,7 @@ class SwipeToDismissHandler(
}
return true
}
else -> {
else -> {
return false
}
}
@ -79,8 +79,8 @@ class SwipeToDismissHandler(
private fun onTrackingEnd(parentHeight: Int) {
val animateTo = when {
swipeView.translationY < -translationLimit -> -parentHeight.toFloat()
swipeView.translationY > translationLimit -> parentHeight.toFloat()
else -> 0f
swipeView.translationY > translationLimit -> parentHeight.toFloat()
else -> 0f
}
if (animateTo != 0f && !shouldAnimateDismiss()) {

View file

@ -146,7 +146,7 @@ class VideoViewHolder constructor(itemView: View) :
wasPaused = true
views.videoView.pause()
}
is AttachmentCommands.SeekTo -> {
is AttachmentCommands.SeekTo -> {
val duration = views.videoView.duration
if (duration > 0) {
val seekDuration = duration * (commands.percentProgress / 100f)

View file

@ -43,7 +43,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
text(async.error.localizedMessage?.toEpoxyCharSequence())
}
}
else -> {
else -> {
async.invoke()?.let {
buildRec(it, 0, "")
}
@ -98,7 +98,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
}
}
}
is JSonViewerArray -> {
is JSonViewerArray -> {
if (model.isExpanded) {
open(id, model.key, model.index, depth, false, model)
model.items.forEach {
@ -137,7 +137,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
}
}
}
is JSonViewerLeaf -> {
is JSonViewerLeaf -> {
valueItem {
id(id)
depth(depth)
@ -172,12 +172,12 @@ internal class JSonViewerEpoxyController(private val context: Context) :
private fun valueToSpan(leaf: JSonViewerLeaf): Span {
val host = this
return when (leaf.type) {
JSONType.STRING -> {
JSONType.STRING -> {
span("\"${leaf.stringRes}\"") {
textColor = host.styleProvider.stringColor
}
}
JSONType.NUMBER -> {
JSONType.NUMBER -> {
span(leaf.stringRes) {
textColor = host.styleProvider.numberColor
}
@ -187,7 +187,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
textColor = host.styleProvider.booleanColor
}
}
JSONType.NULL -> {
JSONType.NULL -> {
span("null") {
textColor = host.styleProvider.booleanColor
}

View file

@ -82,7 +82,7 @@ internal object ModelParser {
}
parent.addChild(objectComposed)
}
is JSONArray -> {
is JSONArray -> {
val objectComposed = JSonViewerArray(key, index, obj)
.apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth }
objectComposed.depth = depth
@ -91,25 +91,25 @@ internal object ModelParser {
}
parent.addChild(objectComposed)
}
is String -> {
is String -> {
JSonViewerLeaf(key, index, obj, JSONType.STRING).let {
it.depth = depth
parent.addChild(it)
}
}
is Number -> {
is Number -> {
JSonViewerLeaf(key, index, obj.toString(), JSONType.NUMBER).let {
it.depth = depth
parent.addChild(it)
}
}
is Boolean -> {
is Boolean -> {
JSonViewerLeaf(key, index, obj.toString(), JSONType.BOOLEAN).let {
it.depth = depth
parent.addChild(it)
}
}
else -> {
else -> {
if (obj == JSONObject.NULL) {
JSonViewerLeaf(key, index, "null", JSONType.NULL).let {
it.depth = depth

View file

@ -48,7 +48,7 @@ class FilePicker : Picker<MultiPickerBaseType>() {
type.isMimeTypeVideo() -> selectedUri.toMultiPickerVideoType(context)
type.isMimeTypeImage() -> selectedUri.toMultiPickerImageType(context)
type.isMimeTypeAudio() -> selectedUri.toMultiPickerAudioType(context)
else -> {
else -> {
// Other files
context.contentResolver.query(selectedUri, null, null, null, null)
?.use { cursor ->

View file

@ -31,15 +31,15 @@ class MultiPicker<T> private constructor() {
@Suppress("UNCHECKED_CAST")
fun <T> get(type: MultiPicker<T>): T {
return when (type) {
IMAGE -> ImagePicker() as T
VIDEO -> VideoPicker() as T
MEDIA -> MediaPicker() as T
FILE -> FilePicker() as T
AUDIO -> AudioPicker() as T
CONTACT -> ContactPicker() as T
CAMERA -> CameraPicker() as T
IMAGE -> ImagePicker() as T
VIDEO -> VideoPicker() as T
MEDIA -> MediaPicker() as T
FILE -> FilePicker() as T
AUDIO -> AudioPicker() as T
CONTACT -> ContactPicker() as T
CAMERA -> CameraPicker() as T
CAMERA_VIDEO -> CameraVideoPicker() as T
else -> throw IllegalArgumentException("Unsupported type $type")
else -> throw IllegalArgumentException("Unsupported type $type")
}
}
}

View file

@ -7,6 +7,7 @@
<dimen name="text_size_body">14sp</dimen>
<dimen name="text_size_caption">12sp</dimen>
<dimen name="text_size_micro">10sp</dimen>
<dimen name="text_size_nano">8sp</dimen>
<dimen name="text_size_button">14sp</dimen>

View file

@ -40,4 +40,9 @@
<item name="android:gravity">center</item>
</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>

View file

@ -48,4 +48,9 @@
<item name="lineHeight">16sp</item>
</style>
<style name="Widget.Vector.TextView.Nano">
<item name="android:textAppearance">@style/TextAppearance.Vector.Nano</item>
<item name="lineHeight">16sp</item>
</style>
</resources>

View file

@ -85,4 +85,11 @@
<item name="android:letterSpacing">0.02</item>
</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>

View file

@ -88,7 +88,7 @@ class FlowSession(private val session: Session) {
}
fun liveSyncState(): Flow<SyncState> {
return session.getSyncStateLive().asFlow()
return session.syncService().getSyncStateLive().asFlow()
}
fun livePushers(): Flow<List<Pusher>> {

View file

@ -56,7 +56,7 @@ android {
// that the app's state is completely cleared between tests.
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_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@ -74,6 +74,7 @@ android {
buildTypes {
debug {
testCoverageEnabled true
// Set to true to log privacy or sensible data, such as token
buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData")
// 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/4455
// - 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:logging-interceptor'
@ -175,7 +176,7 @@ dependencies {
implementation libs.androidx.work
// 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
implementation libs.dagger.dagger
@ -192,7 +193,7 @@ dependencies {
implementation libs.apache.commonsImaging
// 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
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281

View file

@ -19,10 +19,14 @@ package org.matrix.android.sdk
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import org.junit.Rule
import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.test.shared.createTimberTestRule
interface InstrumentedTest {
@Rule
fun retryTestRule() = RetryTestRule(3)
@Rule
fun timberTestRule() = createTimberTestRule()

View file

@ -137,11 +137,11 @@ class CommonTestHelper private constructor(context: Context) {
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
val lock = CountDownLatch(1)
coroutineScope.launch {
session.startSync(true)
val syncLiveData = session.getSyncStateLive()
session.syncService().startSync(true)
val syncLiveData = session.syncService().getSyncStateLive()
val syncObserver = object : Observer<SyncState> {
override fun onChanged(t: SyncState?) {
if (session.hasAlreadySynced()) {
if (session.syncService().hasAlreadySynced()) {
lock.countDown()
syncLiveData.removeObserver(this)
}
@ -160,10 +160,10 @@ class CommonTestHelper private constructor(context: Context) {
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
waitWithLatch(timeout) { latch ->
session.clearCache()
val syncLiveData = session.getSyncStateLive()
val syncLiveData = session.syncService().getSyncStateLive()
val syncObserver = object : Observer<SyncState> {
override fun onChanged(t: SyncState?) {
if (session.hasAlreadySynced()) {
if (session.syncService().hasAlreadySynced()) {
Timber.v("Clear cache and synced")
syncLiveData.removeObserver(this)
latch.countDown()
@ -171,7 +171,7 @@ class CommonTestHelper private constructor(context: Context) {
}
}
syncLiveData.observeForever(syncObserver)
session.startSync(true)
session.syncService().startSync(true)
}
}
@ -252,7 +252,8 @@ class CommonTestHelper private constructor(context: Context) {
message: String,
numberOfMessages: Int,
rootThreadEventId: String,
timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
timeout: Long = TestConstants.timeOutMillis
): List<TimelineEvent> {
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
timeline.start()
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
* @return the session associated with the newly created account
*/
private fun createAccount(userNamePrefix: String,
password: String,
testParams: SessionTestParams): Session {
private fun createAccount(
userNamePrefix: String,
password: String,
testParams: SessionTestParams
): Session {
val session = createAccountAndSync(
userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(),
password,
@ -294,9 +297,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param testParams test params about the session
* @return the session associated with the existing account
*/
fun logIntoAccount(userId: String,
password: String,
testParams: SessionTestParams): Session {
fun logIntoAccount(
userId: String,
password: String,
testParams: SessionTestParams
): Session {
val session = logAccountAndSync(userId, password, testParams)
assertNotNull(session)
return session.also {
@ -311,9 +316,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param password the password
* @param sessionTestParams parameters for the test
*/
private fun createAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
private fun createAccountAndSync(
userName: String,
password: String,
sessionTestParams: SessionTestParams
): Session {
val hs = createHomeServerConfig()
runBlockingTest {
@ -349,9 +356,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param password the password
* @param sessionTestParams session test params
*/
private fun logAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
private fun logAccountAndSync(
userName: String,
password: String,
sessionTestParams: SessionTestParams
): Session {
val hs = createHomeServerConfig()
runBlockingTest {
@ -377,8 +386,10 @@ class CommonTestHelper private constructor(context: Context) {
* @param userName the account username
* @param password the password
*/
fun logAccountWithError(userName: String,
password: String): Throwable {
fun logAccountWithError(
userName: String,
password: String
): Throwable {
val hs = createHomeServerConfig()
runBlockingTest {

View file

@ -18,8 +18,10 @@ package org.matrix.android.sdk.common
import org.matrix.android.sdk.api.session.Session
data class CryptoTestData(val roomId: String,
val sessions: List<Session>) {
data class CryptoTestData(
val roomId: String,
val sessions: List<Session>
) {
val firstSession: Session
get() = sessions.first()

View file

@ -73,9 +73,11 @@ class MockOkHttpInterceptor : TestInterceptor {
/**
* Simple rule that reply with the given body for any request that matches the match param
*/
class SimpleRule(match: String,
private val code: Int = HttpsURLConnection.HTTP_OK,
private val body: String = "{}") : Rule(match) {
class SimpleRule(
match: String,
private val code: Int = HttpsURLConnection.HTTP_OK,
private val body: String = "{}"
) : Rule(match) {
override fun process(originalRequest: Request): Response? {
return Response.Builder()

View file

@ -27,8 +27,10 @@ import java.util.concurrent.CountDownLatch
* @param onlySuccessful true to fail if an error occurs. This is the default behavior
* @param <T>
*/
open class TestMatrixCallback<T>(private val countDownLatch: CountDownLatch,
private val onlySuccessful: Boolean = true) : MatrixCallback<T> {
open class TestMatrixCallback<T>(
private val countDownLatch: CountDownLatch,
private val onlySuccessful: Boolean = true
) : MatrixCallback<T> {
@CallSuper
override fun onSuccess(data: T) {

View file

@ -47,7 +47,9 @@ internal interface TestMatrixComponent : MatrixComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context,
@BindsInstance matrixConfiguration: MatrixConfiguration): TestMatrixComponent
fun create(
@BindsInstance context: Context,
@BindsInstance matrixConfiguration: MatrixConfiguration
): TestMatrixComponent
}
}

View file

@ -22,6 +22,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@ -40,6 +41,7 @@ import java.util.UUID
@Suppress("SpellCheckingInspection")
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Ignore
class AttachmentEncryptionTest {
private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {

View file

@ -22,6 +22,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -37,6 +38,7 @@ import org.matrix.olm.OlmSession
private const val DUMMY_DEVICE_KEY = "DeviceKey"
@RunWith(AndroidJUnit4::class)
@Ignore
class CryptoStoreTest : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)

View file

@ -626,7 +626,7 @@ class E2eeSanityTests : InstrumentedTest {
// we can release this latch?
oldCompleteLatch.countDown()
}
else -> Unit
else -> Unit
}
}
})
@ -653,17 +653,17 @@ class E2eeSanityTests : InstrumentedTest {
IncomingSasVerificationTransaction.UxState.SHOW_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) {
sasTx.userHasVerifiedShortCode()
newCode = sasTx.getDecimalCodeRepresentation()
matchOnce = false
}
}
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
newCompleteLatch.countDown()
}
else -> Unit
else -> Unit
}
}
})

View file

@ -21,6 +21,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@ -30,6 +31,7 @@ import org.junit.runners.MethodSorters
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Ignore
class ExportEncryptionTest {
@Test
@ -83,7 +85,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt1() {
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"
var decodedString: String? = null
@ -103,7 +106,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt2() {
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"
var decodedString: String? = null
@ -123,7 +127,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt3() {
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"
var decodedString: String? = null
@ -202,7 +207,8 @@ class ExportEncryptionTest {
@Test
fun checkExportEncrypt4() {
val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null

View file

@ -21,6 +21,7 @@ import org.amshove.kluent.shouldBe
import org.junit.Assert
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@ -59,6 +60,7 @@ import kotlin.coroutines.resume
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@Ignore
class UnwedgingTest : InstrumentedTest {
private lateinit var messagesReceivedByBob: List<TimelineEvent>

View file

@ -25,6 +25,7 @@ import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@ -47,6 +48,7 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
@Ignore
class XSigningTest : InstrumentedTest {
@Test

View file

@ -25,6 +25,7 @@ import org.amshove.kluent.internal.assertEquals
import org.junit.Assert
import org.junit.Assert.assertNull
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -50,6 +51,7 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
@Ignore
class KeyShareTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
@ -422,7 +424,7 @@ class KeyShareTests : InstrumentedTest {
// /!\ Stop initial alice session syncing so that it can't reply
aliceSession.cryptoService().enableKeyGossiping(false)
aliceSession.stopSync()
aliceSession.syncService().stopSync()
// Let's now try to request
aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root)
@ -445,7 +447,7 @@ class KeyShareTests : InstrumentedTest {
// let's wake up alice
aliceSession.cryptoService().enableKeyGossiping(true)
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
// We should now get a reply from first session
commonTestHelper.waitWithLatch { latch ->

View file

@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -46,6 +47,7 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
@Ignore
class WithHeldTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)

View file

@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -55,6 +56,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
@Ignore
class KeysBackupTest : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)

View file

@ -33,7 +33,8 @@ import java.util.concurrent.CountDownLatch
internal class KeysBackupTestHelper(
private val testHelper: CommonTestHelper,
private val cryptoTestHelper: CryptoTestHelper) {
private val cryptoTestHelper: CryptoTestHelper
) {
fun waitForKeybackUpBatching() {
Thread.sleep(400)
@ -96,8 +97,10 @@ internal class KeysBackupTestHelper(
)
}
fun prepareAndCreateKeysBackupData(keysBackup: KeysBackupService,
password: String? = null): PrepareKeysBackupDataResult {
fun prepareAndCreateKeysBackupData(
keysBackup: KeysBackupService,
password: String? = null
): PrepareKeysBackupDataResult {
val stateObserver = StateObserver(keysBackup)
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
@ -169,9 +172,11 @@ internal class KeysBackupTestHelper(
* - The new device must have the same count of megolm keys
* - Alice must have the same keys on both devices
*/
fun checkRestoreSuccess(testData: KeysBackupScenarioData,
total: Int,
imported: Int) {
fun checkRestoreSuccess(
testData: KeysBackupScenarioData,
total: Int,
imported: Int
) {
// - Imported keys number must be correct
Assert.assertEquals(testData.aliceKeys.size, total)
Assert.assertEquals(total, imported)

View file

@ -18,5 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
data class PrepareKeysBackupDataResult(val megolmBackupCreationInfo: MegolmBackupCreationInfo,
val version: String)
data class PrepareKeysBackupDataResult(
val megolmBackupCreationInfo: MegolmBackupCreationInfo,
val version: String
)

View file

@ -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
* It checks all state transitions and detected forbidden transition
*/
internal class StateObserver(private val keysBackup: KeysBackupService,
private val latch: CountDownLatch? = null,
private val expectedStateChange: Int = -1) : KeysBackupStateListener {
internal class StateObserver(
private val keysBackup: KeysBackupService,
private val latch: CountDownLatch? = null,
private val expectedStateChange: Int = -1
) : KeysBackupStateListener {
private val allowedStateTransitions = listOf(
KeysBackupState.BackingUp to KeysBackupState.ReadyToBackUp,

View file

@ -52,6 +52,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Ignore
class SASTest : InstrumentedTest {
@Test
@ -264,14 +265,16 @@ class SASTest : InstrumentedTest {
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
}
private fun fakeBobStart(bobSession: Session,
aliceUserID: String?,
aliceDevice: String?,
tid: String,
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES,
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS,
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES) {
private fun fakeBobStart(
bobSession: Session,
aliceUserID: String?,
aliceDevice: String?,
tid: String,
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES,
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS,
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES
) {
val startMessage = KeyVerificationStart(
fromDevice = bobSession.cryptoService().getMyDevice().deviceId,
method = VerificationMethod.SAS.toValue(),
@ -412,7 +415,7 @@ class SASTest : InstrumentedTest {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
aliceSASLatch.countDown()
}
else -> Unit
else -> Unit
}
}
}
@ -426,7 +429,7 @@ class SASTest : InstrumentedTest {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
tx.performAccept()
}
else -> Unit
else -> Unit
}
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
bobSASLatch.countDown()
@ -476,7 +479,7 @@ class SASTest : InstrumentedTest {
aliceSASLatch.countDown()
}
}
else -> Unit
else -> Unit
}
}
}
@ -496,16 +499,16 @@ class SASTest : InstrumentedTest {
tx.performAccept()
}
}
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
if (matchOnce) {
matchOnce = false
tx.userHasVerifiedShortCode()
}
}
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
bobSASLatch.countDown()
}
else -> Unit
else -> Unit
}
}
}

View file

@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.amshove.kluent.shouldBe
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@ -41,6 +42,7 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@Ignore
class VerificationTest : InstrumentedTest {
data class ExpectedResult(
@ -151,10 +153,12 @@ class VerificationTest : InstrumentedTest {
// TODO Add tests without SAS
private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
bobSupportedMethods: List<VerificationMethod>,
expectedResultForAlice: ExpectedResult,
expectedResultForBob: ExpectedResult) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
private fun doTest(
aliceSupportedMethods: List<VerificationMethod>,
bobSupportedMethods: List<VerificationMethod>,
expectedResultForAlice: ExpectedResult,
expectedResultForBob: ExpectedResult
) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession

View file

@ -289,9 +289,11 @@ class MarkdownParserTest : InstrumentedTest {
markdownParser.parse(text).expect(text, null)
}
private fun testType(name: String,
markdownPattern: String,
htmlExpectedTag: String) {
private fun testType(
name: String,
markdownPattern: String,
htmlExpectedTag: String
) {
// Test simple case
"$markdownPattern$name$markdownPattern"
.let {
@ -376,10 +378,12 @@ class MarkdownParserTest : InstrumentedTest {
}
}
private fun testTypeNewLines(name: String,
markdownPattern: String,
htmlExpectedTag: String,
softBreak: String = "<br />") {
private fun testTypeNewLines(
name: String,
markdownPattern: String,
htmlExpectedTag: String,
softBreak: String = "<br />"
) {
// With new line inside the block
"$markdownPattern$name\n$name$markdownPattern"
.let {

View file

@ -44,7 +44,7 @@ class TestPermalinkService : PermalinkService {
override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String {
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)"
}
}

View file

@ -83,7 +83,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@ -97,7 +97,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
aliceSession.stopSync()
aliceSession.syncService().stopSync()
}
@Test
@ -144,7 +144,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@ -156,9 +156,9 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
aliceSession.stopSync()
aliceSession.syncService().stopSync()
bobSession.startSync(true)
bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@ -170,7 +170,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
bobSession.stopSync()
bobSession.syncService().stopSync()
}
@Test
@ -217,7 +217,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@ -233,7 +233,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
aliceSession.stopSync()
aliceSession.syncService().stopSync()
}
@Test
@ -314,7 +314,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@ -338,6 +338,6 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
aliceSession.stopSync()
aliceSession.syncService().stopSync()
}
}

View file

@ -154,9 +154,11 @@ internal class ChunkEntityTest : InstrumentedTest {
}
}
private fun ChunkEntity.addAll(roomId: String,
events: List<Event>,
direction: PaginationDirection) {
private fun ChunkEntity.addAll(
roomId: String,
events: List<Event>,
direction: PaginationDirection
) {
events.forEach { event ->
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let {
realm.copyToRealm(it)

View file

@ -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.internal.session.room.timeline.TokenChunkEvent
internal data class FakeTokenChunkEvent(override val start: String?,
override val end: String?,
override val events: List<Event> = emptyList(),
override val stateEvents: List<Event> = emptyList()
internal data class FakeTokenChunkEvent(
override val start: String?,
override val end: String?,
override val events: List<Event> = emptyList(),
override val stateEvents: List<Event> = emptyList()
) : TokenChunkEvent

View file

@ -57,7 +57,7 @@ class PollAggregationTest : InstrumentedTest {
// Bob creates a poll
roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
aliceSession.startSync(true)
aliceSession.syncService().startSync(true)
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
aliceTimeline.start()
@ -77,7 +77,7 @@ class PollAggregationTest : InstrumentedTest {
}
when (lock.count.toInt()) {
TOTAL_TEST_COUNT -> {
TOTAL_TEST_COUNT -> {
// Poll has just been created.
testInitialPollConditions(pollContent, pollSummary)
lock.countDown()
@ -119,7 +119,7 @@ class PollAggregationTest : InstrumentedTest {
testEndedPoll(pollSummary)
lock.countDown()
}
else -> {
else -> {
fail("Lock count ${lock.count} didn't handled.")
}
}
@ -133,7 +133,7 @@ class PollAggregationTest : InstrumentedTest {
aliceTimeline.removeAllListeners()
aliceSession.stopSync()
aliceSession.syncService().stopSync()
aliceTimeline.dispose()
}

View file

@ -41,11 +41,12 @@ object RoomDataHelper {
}
}
private fun createFakeEvent(type: String,
content: Content? = null,
prevContent: Content? = null,
sender: String = FAKE_TEST_SENDER,
stateKey: String? = null
private fun createFakeEvent(
type: String,
content: Content? = null,
prevContent: Content? = null,
sender: String = FAKE_TEST_SENDER,
stateKey: String? = null
): Event {
return Event(
type = type,

View file

@ -88,7 +88,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
bobSession.stopSync()
bobSession.syncService().stopSync()
val firstMessage = "First messages from Alice"
// Alice sends 30 messages
@ -101,7 +101,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
.eventId
// Bob start to sync
bobSession.startSync(true)
bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@ -125,7 +125,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
bobSession.stopSync()
bobSession.syncService().stopSync()
val secondMessage = "Second messages from Alice"
// Alice sends again 30 messages
@ -136,7 +136,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
)
// Bob start to sync
bobSession.startSync(true)
bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)

View file

@ -20,6 +20,7 @@ import androidx.test.filters.LargeTest
import kotlinx.coroutines.runBlocking
import org.amshove.kluent.internal.assertEquals
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@ -38,6 +39,7 @@ import org.matrix.android.sdk.common.TestConstants
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
@Ignore
class TimelineSimpleBackPaginationTest : InstrumentedTest {
@Test

View file

@ -71,7 +71,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30))
timelineForCurrentMember.start()
session.startSync(true)
session.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@ -92,7 +92,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
timelineForCurrentMember.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
session.stopSync()
session.syncService().stopSync()
}
}
}

View file

@ -22,6 +22,7 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@ -98,6 +99,7 @@ class SpaceCreationTest : InstrumentedTest {
}
@Test
@Ignore
fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))

View file

@ -387,9 +387,10 @@ class SpaceHierarchyTest : InstrumentedTest {
val roomIds: List<String>
)
private fun createPublicSpace(session: Session,
spaceName: String,
childInfo: List<Triple<String, Boolean, Boolean?>>
private fun createPublicSpace(
session: Session,
spaceName: String,
childInfo: List<Triple<String, Boolean, Boolean?>>
/** Name, auto-join, canonical*/
): TestSpaceCreationResult {
var spaceId = ""
@ -416,9 +417,10 @@ class SpaceHierarchyTest : InstrumentedTest {
return TestSpaceCreationResult(spaceId, roomIds)
}
private fun createPrivateSpace(session: Session,
spaceName: String,
childInfo: List<Triple<String, Boolean, Boolean?>>
private fun createPrivateSpace(
session: Session,
spaceName: String,
childInfo: List<Triple<String, Boolean, Boolean?>>
/** Name, auto-join, canonical*/
): TestSpaceCreationResult {
var spaceId = ""

View file

@ -26,14 +26,14 @@ internal class InlineMaths(private val delimiter: InlineDelimiter) : CustomNode(
override fun getOpeningDelimiter(): String {
return when (delimiter) {
InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\("
}
}
override fun getClosingDelimiter(): String {
return when (delimiter) {
InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\)"
}
}

View file

@ -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.
*/
interface AuthenticationService {
/**
* 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
@ -93,14 +95,18 @@ interface AuthenticationService {
/**
* Create a session after a SSO successful login.
*/
suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
credentials: Credentials): Session
suspend fun createSessionFromSso(
homeServerConnectionConfig: HomeServerConnectionConfig,
credentials: Credentials
): Session
/**
* Perform a wellknown request, using the domain from the matrixId.
*/
suspend fun getWellKnownData(matrixId: String,
homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult
suspend fun getWellKnownData(
matrixId: String,
homeServerConnectionConfig: HomeServerConnectionConfig?
): WellknownResult
/**
* Authenticate with a matrixId and a password.
@ -111,9 +117,11 @@ interface AuthenticationService {
* @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
*/
suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String,
password: String,
initialDeviceName: String,
deviceId: String? = null): Session
suspend fun directAuthentication(
homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String,
password: String,
initialDeviceName: String,
deviceId: String? = null
): Session
}

View file

@ -41,8 +41,10 @@ import org.matrix.android.sdk.api.auth.registration.TermPolicies
* @param userLanguage the user language
* @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse
*/
fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
defaultLanguage: String = "en"): List<LocalizedFlowDataLoginTerms> {
fun TermPolicies.toLocalizedLoginTerms(
userLanguage: String,
defaultLanguage: String = "en"
): List<LocalizedFlowDataLoginTerms> {
val result = ArrayList<LocalizedFlowDataLoginTerms>()
val policies = get("policies")
@ -67,8 +69,8 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// Search for language
policy.keys.forEach { policyKey ->
when (policyKey) {
"version" -> Unit // Ignore
userLanguage -> {
"version" -> Unit // Ignore
userLanguage -> {
// We found the data for the user language
userLanguageUrlAndName = extractUrlAndName(policy[policyKey])
}
@ -76,7 +78,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// We found default language
defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey])
}
else -> {
else -> {
if (firstUrlAndName == null) {
// Get at least some data
firstUrlAndName = extractUrlAndName(policy[policyKey])
@ -87,7 +89,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// Copy found language data by priority
when {
userLanguageUrlAndName != null -> {
userLanguageUrlAndName != null -> {
localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name
}
@ -95,7 +97,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name
}
firstUrlAndName != null -> {
firstUrlAndName != null -> {
localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name
}

View file

@ -66,17 +66,17 @@ data class SsoIdentityProvider(
private fun toPriority(): Int {
return when (brand) {
// 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
BRAND_FACEBOOK -> 4
// Twitter is more for professionals
BRAND_TWITTER -> 3
BRAND_TWITTER -> 3
// Here it's very for techie people
BRAND_GITHUB,
BRAND_GITLAB -> 2
BRAND_GITLAB -> 2
// And finally, if the account has been created with an iPhone...
BRAND_APPLE -> 1
else -> 0
BRAND_APPLE -> 1
else -> 0
}
}
}

View file

@ -39,10 +39,12 @@ interface LoginWizard {
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
* @return a [Session] if the login is successful
*/
suspend fun login(login: String,
password: String,
initialDeviceName: String,
deviceId: String? = null): Session
suspend fun login(
login: String,
password: String,
initialDeviceName: String,
deviceId: String? = null
): Session
/**
* Exchange a login token to an access token.
@ -63,14 +65,14 @@ interface LoginWizard {
* [resetPasswordMailConfirmed] is successfully called.
*
* @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,
newPassword: String)
suspend fun resetPassword(email: String)
/**
* Confirm the new password, once the user has checked their email
* 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)
}

View file

@ -88,15 +88,15 @@ fun RegistrationFlowResponse.toFlowResult(): FlowResult {
val isMandatory = flows?.all { type in it.stages.orEmpty() } == true
val stage = when (type) {
LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String)
?: ""
)
LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap<String, String>())
LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap<String, String>())
LoginFlowTypes.EMAIL_IDENTITY -> Stage.Email(isMandatory)
LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
}
if (type in completedStages.orEmpty()) {

View file

@ -54,9 +54,11 @@ interface RegistrationWizard {
* @param password the desired password
* @param initialDeviceDisplayName the device display name
*/
suspend fun createAccount(userName: String?,
password: String?,
initialDeviceDisplayName: String?): RegistrationResult
suspend fun createAccount(
userName: String?,
password: String?,
initialDeviceDisplayName: String?
): RegistrationResult
/**
* Perform the "m.login.recaptcha" stage.

View file

@ -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,
* 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,
val identityServerUrl: String?,
val wellKnown: WellKnown) : WellknownResult()
data class Prompt(
val homeServerUrl: String,
val identityServerUrl: String?,
val wellKnown: WellKnown
) : WellknownResult()
/**
* Stop the current auto-discovery mechanism. If no more auto-discovery mechanisms are available,

View file

@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.extensions
fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
return when {
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.
*/
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
/**
* Returns null if the string is empty.
*/
fun String.ensureNotEmpty() = ifEmpty { null }

View file

@ -36,7 +36,7 @@ data class Fingerprint(
internal fun matchesCert(cert: X509Certificate): Boolean {
val o: Fingerprint? = when (hashType) {
HashType.SHA256 -> newSha256Fingerprint(cert)
HashType.SHA1 -> newSha1Fingerprint(cert)
HashType.SHA1 -> newSha1Fingerprint(cert)
}
return equals(o)
}

View file

@ -17,8 +17,6 @@
package org.matrix.android.sdk.api.session
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import kotlinx.coroutines.flow.SharedFlow
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
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.homeserver.HomeServerCapabilitiesService
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.media.MediaService
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.statistics.StatisticsListener
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.model.SyncResponse
import org.matrix.android.sdk.api.session.sync.SyncService
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.typing.TypingUsersTracker
@ -98,59 +94,11 @@ interface Session {
@MainThread
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.
*/
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.
*/
@ -247,9 +195,9 @@ interface Session {
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.

View file

@ -27,8 +27,10 @@ interface AccountService {
* @param password Current password.
* @param newPassword New password
*/
suspend fun changePassword(password: String,
newPassword: String)
suspend fun changePassword(
password: String,
newPassword: String
)
/**
* Deactivate the account.
@ -46,6 +48,8 @@ interface AccountService {
* an incomplete view of conversations
* @param userInteractiveAuthInterceptor see [UserInteractiveAuthInterceptor]
*/
suspend fun deactivateAccount(eraseAllData: Boolean,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
suspend fun deactivateAccount(
eraseAllData: Boolean,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor
)
}

View file

@ -91,10 +91,12 @@ interface MxCall : MxCallDetail {
* 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
*/
suspend fun transfer(targetUserId: String,
targetRoomId: String?,
createCallId: String?,
awaitCallId: String?)
suspend fun transfer(
targetUserId: String,
targetRoomId: String?,
createCallId: String?,
awaitCallId: String?
)
fun addListener(listener: StateListener)
fun removeListener(listener: StateListener)

View file

@ -88,9 +88,11 @@ interface CryptoService {
fun getDeviceTrackingStatus(userId: String): Int
suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
password: String,
progressListener: ProgressListener?): ImportRoomKeysResult
suspend fun importRoomKeys(
roomKeysAsArray: ByteArray,
password: String,
progressListener: ProgressListener?
): ImportRoomKeysResult
suspend fun exportRoomKeys(password: String): ByteArray
@ -119,10 +121,12 @@ interface CryptoService {
fun isRoomEncrypted(roomId: String): Boolean
// TODO This could be removed from this interface
fun encryptEventContent(eventContent: Content,
eventType: String,
roomId: String,
callback: MatrixCallback<MXEncryptEventContentResult>)
fun encryptEventContent(
eventContent: Content,
eventType: String,
roomId: String,
callback: MatrixCallback<MXEncryptEventContentResult>
)
fun discardOutboundSession(roomId: String)

View file

@ -25,12 +25,14 @@ import org.matrix.olm.OlmException
*/
sealed class MXCryptoError : Throwable() {
data class Base(val errorType: ErrorType,
val technicalMessage: String,
/**
* Describe the error with more details.
*/
val detailedErrorDescription: String? = null) : MXCryptoError()
data class Base(
val errorType: ErrorType,
val technicalMessage: String,
/**
* Describe the error with more details.
*/
val detailedErrorDescription: String? = null
) : MXCryptoError()
data class OlmError(val olmException: OlmException) : MXCryptoError()

View file

@ -26,7 +26,7 @@ data class RequestReply(
)
sealed class RequestResult {
data class Success(val chainIndex: Int) : RequestResult()
data class Success(val chainIndex: Int) : RequestResult()
data class Failure(val code: WithHeldCode) : RequestResult()
}

View file

@ -37,14 +37,18 @@ interface CrossSigningService {
* Initialize cross signing for this user.
* Users needs to enter credentials
*/
fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?,
callback: MatrixCallback<Unit>)
fun initializeCrossSigning(
uiaInterceptor: UserInteractiveAuthInterceptor?,
callback: MatrixCallback<Unit>
)
fun isCrossSigningInitialized(): Boolean = getMyCrossSigningKeys() != null
fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
uskKeyPrivateKey: String?,
sskPrivateKey: String?): UserTrustResult
fun checkTrustFromPrivateKeys(
masterKeyPrivateKey: String?,
uskKeyPrivateKey: String?,
sskPrivateKey: String?
): UserTrustResult
fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo?
@ -60,20 +64,26 @@ interface CrossSigningService {
fun allPrivateKeysKnown(): Boolean
fun trustUser(otherUserId: String,
callback: MatrixCallback<Unit>)
fun trustUser(
otherUserId: String,
callback: MatrixCallback<Unit>
)
fun markMyMasterKeyAsTrusted()
/**
* Sign one of your devices and upload the signature.
*/
fun trustDevice(deviceId: String,
callback: MatrixCallback<Unit>)
fun trustDevice(
deviceId: String,
callback: MatrixCallback<Unit>
)
fun checkDeviceTrust(otherUserId: String,
otherDeviceId: String,
locallyTrusted: Boolean?): DeviceTrustResult
fun checkDeviceTrust(
otherUserId: String,
otherDeviceId: String,
locallyTrusted: Boolean?
): DeviceTrustResult
// FIXME Those method do not have to be in the service
fun onSecretMSKGossip(mskPrivateKey: String)

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