Merge branch 'develop' into renovate/org.maplibre.gl-android-sdk-11.x
This commit is contained in:
commit
395b3c4806
1249 changed files with 18041 additions and 8127 deletions
2
.github/workflows/danger.yml
vendored
2
.github/workflows/danger.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||||
- name: Danger
|
- name: Danger
|
||||||
uses: danger/danger-js@12.2.0
|
uses: danger/danger-js@12.3.0
|
||||||
with:
|
with:
|
||||||
args: "--dangerfile ./tools/danger/dangerfile.js"
|
args: "--dangerfile ./tools/danger/dangerfile.js"
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
2
.github/workflows/nightlyReports.yml
vendored
2
.github/workflows/nightlyReports.yml
vendored
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
run: ./gradlew verifyPaparazziDebug $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew verifyPaparazziDebug $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
- name: 📈 Generate kover report and verify coverage
|
- name: 📈 Generate kover report and verify coverage
|
||||||
run: ./gradlew :app:koverXmlReportGplayDebug :app:koverHtmlReportGplayDebug :app:koverVerifyGplayDebug $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew :app:koverXmlReportGplayDebug :app:koverHtmlReportGplayDebug :app:koverVerifyAll $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
- name: ✅ Upload kover report
|
- name: ✅ Upload kover report
|
||||||
if: always()
|
if: always()
|
||||||
|
|
|
||||||
149
.github/workflows/quality.yml
vendored
149
.github/workflows/quality.yml
vendored
|
|
@ -10,7 +10,7 @@ on:
|
||||||
# Enrich gradle.properties for CI/CD
|
# Enrich gradle.properties for CI/CD
|
||||||
env:
|
env:
|
||||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx6g -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.incremental=false -XX:+UseParallelGC
|
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx6g -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.incremental=false -XX:+UseParallelGC
|
||||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 8 --no-daemon --warn
|
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 8 --no-daemon
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
checkScript:
|
checkScript:
|
||||||
|
|
@ -33,12 +33,13 @@ jobs:
|
||||||
- name: Search for invalid screenshot files
|
- name: Search for invalid screenshot files
|
||||||
run: ./tools/test/checkInvalidScreenshots.py
|
run: ./tools/test/checkInvalidScreenshots.py
|
||||||
|
|
||||||
check:
|
# Code checks
|
||||||
name: Project Check Suite
|
konsist:
|
||||||
|
name: Konsist tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Allow all jobs on main and develop. Just one per PR.
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.ref == 'refs/heads/main' && format('check-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-develop-{0}', github.sha) || format('check-{0}', github.ref) }}
|
group: ${{ github.ref == 'refs/heads/main' && format('check-konsist-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-konsist-develop-{0}', github.sha) || format('check-konsist-{0}', github.ref) }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -55,8 +56,40 @@ jobs:
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/actions/setup-gradle@v3
|
||||||
with:
|
with:
|
||||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
- name: Run code quality check suite
|
- name: Run Konsist tests
|
||||||
run: ./gradlew runQualityChecks $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew :tests:konsist:testDebugUnitTest $CI_GRADLE_ARG_PROPERTIES --no-daemon
|
||||||
|
- name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: konsist-report
|
||||||
|
path: |
|
||||||
|
**/build/reports/**/*.*
|
||||||
|
|
||||||
|
lint:
|
||||||
|
name: Android lint check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('check-lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-lint-develop-{0}', github.sha) || format('check-lint-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Use JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
- name: Run lint
|
||||||
|
run: ./gradlew :app:lintGplayDebug :app:lintFdroidDebug $CI_GRADLE_ARG_PROPERTIES
|
||||||
- name: Upload reports
|
- name: Upload reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
@ -64,6 +97,108 @@ jobs:
|
||||||
name: linting-report
|
name: linting-report
|
||||||
path: |
|
path: |
|
||||||
**/build/reports/**/*.*
|
**/build/reports/**/*.*
|
||||||
|
|
||||||
|
detekt:
|
||||||
|
name: Detekt checks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('check-detekt-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-detekt-develop-{0}', github.sha) || format('check-detekt-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Use JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
- name: Run Detekt
|
||||||
|
run: ./gradlew detekt $CI_GRADLE_ARG_PROPERTIES --no-daemon
|
||||||
|
- name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: detekt-report
|
||||||
|
path: |
|
||||||
|
**/build/reports/**/*.*
|
||||||
|
|
||||||
|
ktlint:
|
||||||
|
name: Ktlint checks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('check-ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-ktlint-develop-{0}', github.sha) || format('check-ktlint-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Use JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
- name: Run Ktlint check
|
||||||
|
run: ./gradlew ktlintCheck $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
- name: Upload reports
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ktlint-report
|
||||||
|
path: |
|
||||||
|
**/build/reports/**/*.*
|
||||||
|
|
||||||
|
knit:
|
||||||
|
name: Knit checks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('check-knit-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-knit-develop-{0}', github.sha) || format('check-knit-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Use JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
- name: Run Knit
|
||||||
|
run: ./gradlew knitCheck $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
|
upload_reports:
|
||||||
|
name: Project Check Suite
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [konsist, lint, ktlint, detekt]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Download reports from previous jobs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
- name: Prepare Danger
|
- name: Prepare Danger
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -72,7 +207,7 @@ jobs:
|
||||||
yarn add danger-plugin-lint-report --dev
|
yarn add danger-plugin-lint-report --dev
|
||||||
- name: Danger lint
|
- name: Danger lint
|
||||||
if: always()
|
if: always()
|
||||||
uses: danger/danger-js@12.2.0
|
uses: danger/danger-js@12.3.0
|
||||||
with:
|
with:
|
||||||
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
|
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
36
.github/workflows/release.yml
vendored
36
.github/workflows/release.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
name: Create release App Bundle
|
name: Create release App Bundle and APKs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
@ -11,11 +11,11 @@ env:
|
||||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 8 --no-daemon
|
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 8 --no-daemon
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
gplay:
|
||||||
name: Create App Bundle
|
name: Create App Bundle (Gplay)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.ref == 'refs/head/main' && format('build-release-main-{0}', github.sha) }}
|
group: ${{ github.ref == 'refs/head/main' && format('build-release-main-gplay-{0}', github.sha) }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -38,3 +38,31 @@ jobs:
|
||||||
name: elementx-app-gplay-bundle-unsigned
|
name: elementx-app-gplay-bundle-unsigned
|
||||||
path: |
|
path: |
|
||||||
app/build/outputs/bundle/gplayRelease/app-gplay-release.aab
|
app/build/outputs/bundle/gplayRelease/app-gplay-release.aab
|
||||||
|
|
||||||
|
fdroid:
|
||||||
|
name: Create APKs (FDroid)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/head/main' && format('build-release-main-fdroid-{0}', github.sha) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Use JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
- name: Create APKs
|
||||||
|
env:
|
||||||
|
ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }}
|
||||||
|
ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }}
|
||||||
|
ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }}
|
||||||
|
run: ./gradlew assembleFdroidRelease $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
- name: Upload apks as artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: elementx-app-fdroid-apks-unsigned
|
||||||
|
path: |
|
||||||
|
app/build/outputs/apk/fdroid/release/*.apk
|
||||||
|
|
|
||||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
|
|
@ -55,7 +55,7 @@ jobs:
|
||||||
run: ./gradlew verifyPaparazziDebug $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew verifyPaparazziDebug $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
- name: 📈Generate kover report and verify coverage
|
- name: 📈Generate kover report and verify coverage
|
||||||
run: ./gradlew :app:koverXmlReportGplayDebug :app:koverHtmlReportGplayDebug :app:koverVerifyGplayDebug $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew :app:koverXmlReportGplayDebug :app:koverHtmlReportGplayDebug :app:koverVerifyAll $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
- name: 🚫 Upload kover failed coverage reports
|
- name: 🚫 Upload kover failed coverage reports
|
||||||
if: failure()
|
if: failure()
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -45,6 +45,7 @@ captures/
|
||||||
.idea/assetWizardSettings.xml
|
.idea/assetWizardSettings.xml
|
||||||
.idea/compiler.xml
|
.idea/compiler.xml
|
||||||
.idea/deploymentTargetDropDown.xml
|
.idea/deploymentTargetDropDown.xml
|
||||||
|
.idea/deploymentTargetSelector.xml
|
||||||
.idea/gradle.xml
|
.idea/gradle.xml
|
||||||
.idea/jarRepositories.xml
|
.idea/jarRepositories.xml
|
||||||
.idea/misc.xml
|
.idea/misc.xml
|
||||||
|
|
|
||||||
2
.idea/dictionaries/shared.xml
generated
2
.idea/dictionaries/shared.xml
generated
|
|
@ -3,7 +3,9 @@
|
||||||
<words>
|
<words>
|
||||||
<w>backstack</w>
|
<w>backstack</w>
|
||||||
<w>blurhash</w>
|
<w>blurhash</w>
|
||||||
|
<w>fdroid</w>
|
||||||
<w>ftue</w>
|
<w>ftue</w>
|
||||||
|
<w>gplay</w>
|
||||||
<w>homeserver</w>
|
<w>homeserver</w>
|
||||||
<w>konsist</w>
|
<w>konsist</w>
|
||||||
<w>kover</w>
|
<w>kover</w>
|
||||||
|
|
|
||||||
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="KotlinJpsPluginSettings">
|
<component name="KotlinJpsPluginSettings">
|
||||||
<option name="version" value="1.9.23" />
|
<option name="version" value="1.9.24" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -2,7 +2,7 @@ appId: ${MAESTRO_APP_ID}
|
||||||
---
|
---
|
||||||
- takeScreenshot: build/maestro/510-Timeline
|
- takeScreenshot: build/maestro/510-Timeline
|
||||||
- tapOn:
|
- tapOn:
|
||||||
id: "rich_text_editor"
|
id: "text_editor"
|
||||||
- inputText: "Hello world!"
|
- inputText: "Hello world!"
|
||||||
- tapOn: "Send"
|
- tapOn: "Send"
|
||||||
- hideKeyboard
|
- hideKeyboard
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ appId: ${MAESTRO_APP_ID}
|
||||||
|
|
||||||
- tapOn:
|
- tapOn:
|
||||||
text: "Advanced settings"
|
text: "Advanced settings"
|
||||||
- assertVisible: "Rich text editor"
|
- assertVisible: "View source"
|
||||||
- back
|
- back
|
||||||
|
|
||||||
- tapOn:
|
- tapOn:
|
||||||
|
|
|
||||||
565
CHANGES.md
565
CHANGES.md
|
|
@ -1,3 +1,64 @@
|
||||||
|
Changes in Element X v0.4.13 (2024-05-22)
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
Features ✨
|
||||||
|
----------
|
||||||
|
- Add plain text editor based on Markdown input. ([#2840](https://github.com/element-hq/element-x-android/issues/2840))
|
||||||
|
|
||||||
|
Bugfixes 🐛
|
||||||
|
----------
|
||||||
|
- Use members display names for their membership state events. ([#2286](https://github.com/element-hq/element-x-android/issues/2286))
|
||||||
|
- Make sure explicit links in messages take priority over links found by linkification (urls, emails, phone numbers, etc.) ([#2291](https://github.com/element-hq/element-x-android/issues/2291))
|
||||||
|
- Fix modal contents overlapping screen lock pin. ([#2692](https://github.com/element-hq/element-x-android/issues/2692))
|
||||||
|
- Fix a crash when trying to create an `EncryptedFile` in Android 6. ([#2846](https://github.com/element-hq/element-x-android/issues/2846))
|
||||||
|
- Session falsely displayed as 'verified' with no internet connection. ([#2884](https://github.com/element-hq/element-x-android/issues/2884))
|
||||||
|
|
||||||
|
Other changes
|
||||||
|
-------------
|
||||||
|
- Allow configuring push notification provider ([#2340](https://github.com/element-hq/element-x-android/issues/2340))
|
||||||
|
- UX cleanup: reorder text composer actions to prioritise camera ones. ([#2803](https://github.com/element-hq/element-x-android/issues/2803))
|
||||||
|
- Translation added into Portuguese and Simplified Chinese ([#2834](https://github.com/element-hq/element-x-android/issues/2834))
|
||||||
|
- Use via parameters when joining a room from permalink. ([#2843](https://github.com/element-hq/element-x-android/issues/2843))
|
||||||
|
|
||||||
|
|
||||||
|
Changes in Element X v0.4.12 (2024-05-13)
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
Features ✨
|
||||||
|
----------
|
||||||
|
- Add support for expected decryption errors due to membership (UX and analytics). ([#2754](https://github.com/element-hq/element-x-android/issues/2754))
|
||||||
|
- Handle permalink navigation to Events. ([#2759](https://github.com/element-hq/element-x-android/issues/2759))
|
||||||
|
- Pretty-print event JSON in debug viewer ([#2771](https://github.com/element-hq/element-x-android/issues/2771))
|
||||||
|
- Add support for external permalinks. ([#2776](https://github.com/element-hq/element-x-android/issues/2776))
|
||||||
|
- Enable support for Android per-app language preferences ([#2795](https://github.com/element-hq/element-x-android/issues/2795))
|
||||||
|
|
||||||
|
Bugfixes 🐛
|
||||||
|
----------
|
||||||
|
- Fix session verification being asked again for already verified users. ([#2718](https://github.com/element-hq/element-x-android/issues/2718))
|
||||||
|
- Instead of displaying 'create new recovery key' on the session verification screen when there is no other session active, display it always under the 'enter recovery key' screen. ([#2740](https://github.com/element-hq/element-x-android/issues/2740))
|
||||||
|
- Adjust the typography used in the selected user component so a user's display name fits better. ([#2760](https://github.com/element-hq/element-x-android/issues/2760))
|
||||||
|
- User display name overflows in timeline messages when it's way too long. ([#2761](https://github.com/element-hq/element-x-android/issues/2761))
|
||||||
|
- Ensure the application open the room when a notification is clicked. ([#2778](https://github.com/element-hq/element-x-android/issues/2778))
|
||||||
|
- Enforce mandatory session verification only for new logins. ([#2810](https://github.com/element-hq/element-x-android/issues/2810))
|
||||||
|
- Make log less verbose, make sure we upload as many log files as possible before reaching the request size limit of the bug reporting service, discard older logs if they don't fit. ([#2825](https://github.com/element-hq/element-x-android/issues/2825))
|
||||||
|
- Remove 'Join' button in room directory search results. ([#2827](https://github.com/element-hq/element-x-android/issues/2827))
|
||||||
|
- Add missing `app_id` and `Version` properties to bug reports. ([#2829](https://github.com/element-hq/element-x-android/issues/2829))
|
||||||
|
|
||||||
|
Other changes
|
||||||
|
-------------
|
||||||
|
- RoomMember screen: fallback to userProfile data, if the member is not a user of the room. ([#2721](https://github.com/element-hq/element-x-android/issues/2721))
|
||||||
|
- Migrate application data. ([#2749](https://github.com/element-hq/element-x-android/issues/2749))
|
||||||
|
- Let the SDK manage the file log cleanup, and keep one week of log. ([#2758](https://github.com/element-hq/element-x-android/issues/2758))
|
||||||
|
- UX cleanup: reorder options in the main settings screen. ([#2801](https://github.com/element-hq/element-x-android/issues/2801))
|
||||||
|
- Analytics: Add support to report current session verification and recovery state ([#2806](https://github.com/element-hq/element-x-android/issues/2806))
|
||||||
|
- UX cleanup: room details screen, add new CTA buttons for Invite and Call actions. ([#2814](https://github.com/element-hq/element-x-android/issues/2814))
|
||||||
|
- UX cleanup: user profile. Move send DM to a call to action button, add 'Call' CTA too. ([#2818](https://github.com/element-hq/element-x-android/issues/2818))
|
||||||
|
- Add room badges to room details screen. ([#2822](https://github.com/element-hq/element-x-android/issues/2822))
|
||||||
|
|
||||||
|
Security
|
||||||
|
-------------
|
||||||
|
- Bump the Rust SDK to `v0.2.18` to remediate [CVE-2024-34353 / GHSA-9ggc-845v-gcgv](https://github.com/matrix-org/matrix-rust-sdk/security/advisories/GHSA-9ggc-845v-gcgv).
|
||||||
|
|
||||||
Changes in Element X v0.4.10 (2024-04-17)
|
Changes in Element X v0.4.10 (2024-04-17)
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
@ -5,14 +66,14 @@ Matrix Rust SDK 0.2.14
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Rework room navigation to handle unknown room and prepare work on permalink. ([#2695](https://github.com/element-hq/element-x-android/issues/2695))
|
- Rework room navigation to handle unknown room and prepare work on permalink. ([#2695](https://github.com/element-hq/element-x-android/issues/2695))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Encrypt new session data with a passphrase ([#2703](https://github.com/element-hq/element-x-android/issues/2703))
|
- Encrypt new session data with a passphrase ([#2703](https://github.com/element-hq/element-x-android/issues/2703))
|
||||||
- Use sdk API to build permalinks ([#2708](https://github.com/element-hq/element-x-android/issues/2708))
|
- Use sdk API to build permalinks ([#2708](https://github.com/element-hq/element-x-android/issues/2708))
|
||||||
- Parse permalink using parseMatrixEntityFrom from the SDK ([#2709](https://github.com/element-hq/element-x-android/issues/2709))
|
- Parse permalink using parseMatrixEntityFrom from the SDK ([#2709](https://github.com/element-hq/element-x-android/issues/2709))
|
||||||
- Fix compile for forks that use the `noop` analytics module ([#2698](https://github.com/element-hq/element-x-android/issues/2698))
|
- Fix compile for forks that use the `noop` analytics module ([#2698](https://github.com/element-hq/element-x-android/issues/2698))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.9 (2024-04-12)
|
Changes in Element X v0.4.9 (2024-04-12)
|
||||||
|
|
@ -29,26 +90,26 @@ Changes in Element X v0.4.8 (2024-04-10)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Move session recovery to the login flow. ([#2579](https://github.com/element-hq/element-x-android/issues/2579))
|
- Move session recovery to the login flow. ([#2579](https://github.com/element-hq/element-x-android/issues/2579))
|
||||||
- Move session verification to the after login flow and make it mandatory. ([#2580](https://github.com/element-hq/element-x-android/issues/2580))
|
- Move session verification to the after login flow and make it mandatory. ([#2580](https://github.com/element-hq/element-x-android/issues/2580))
|
||||||
- Add a notification troubleshoot screen ([#2601](https://github.com/element-hq/element-x-android/issues/2601))
|
- Add a notification troubleshoot screen ([#2601](https://github.com/element-hq/element-x-android/issues/2601))
|
||||||
- Add action to copy permalink ([#2650](https://github.com/element-hq/element-x-android/issues/2650))
|
- Add action to copy permalink ([#2650](https://github.com/element-hq/element-x-android/issues/2650))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix analytics issue around room considered as space by mistake. ([#2612](https://github.com/element-hq/element-x-android/issues/2612))
|
- Fix analytics issue around room considered as space by mistake. ([#2612](https://github.com/element-hq/element-x-android/issues/2612))
|
||||||
- Fix crash observed when going back to the room list. ([#2619](https://github.com/element-hq/element-x-android/issues/2619))
|
- Fix crash observed when going back to the room list. ([#2619](https://github.com/element-hq/element-x-android/issues/2619))
|
||||||
- Hide Event org.matrix.msc3401.call.member on the timeline. ([#2625](https://github.com/element-hq/element-x-android/issues/2625))
|
- Hide Event org.matrix.msc3401.call.member on the timeline. ([#2625](https://github.com/element-hq/element-x-android/issues/2625))
|
||||||
- Fall back to name-based generated avatars when image avatars don't load. ([#2667](https://github.com/element-hq/element-x-android/issues/2667))
|
- Fall back to name-based generated avatars when image avatars don't load. ([#2667](https://github.com/element-hq/element-x-android/issues/2667))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Improve UI for notification permission screen in onboarding. ([#2581](https://github.com/element-hq/element-x-android/issues/2581))
|
- Improve UI for notification permission screen in onboarding. ([#2581](https://github.com/element-hq/element-x-android/issues/2581))
|
||||||
- Categorise members by role in change roles screen. ([#2593](https://github.com/element-hq/element-x-android/issues/2593))
|
- Categorise members by role in change roles screen. ([#2593](https://github.com/element-hq/element-x-android/issues/2593))
|
||||||
- Make completed poll more clearly visible ([#2608](https://github.com/element-hq/element-x-android/issues/2608))
|
- Make completed poll more clearly visible ([#2608](https://github.com/element-hq/element-x-android/issues/2608))
|
||||||
- Show users from last visited DM as suggestion when starting a Chat or when creating a Room. ([#2634](https://github.com/element-hq/element-x-android/issues/2634))
|
- Show users from last visited DM as suggestion when starting a Chat or when creating a Room. ([#2634](https://github.com/element-hq/element-x-android/issues/2634))
|
||||||
- Enable room moderation feature. ([#2678](https://github.com/element-hq/element-x-android/issues/2678))
|
- Enable room moderation feature. ([#2678](https://github.com/element-hq/element-x-android/issues/2678))
|
||||||
- Improve analytics opt-in screen UI. ([#2684](https://github.com/element-hq/element-x-android/issues/2684))
|
- Improve analytics opt-in screen UI. ([#2684](https://github.com/element-hq/element-x-android/issues/2684))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.7 (2024-03-26)
|
Changes in Element X v0.4.7 (2024-03-26)
|
||||||
|
|
@ -56,19 +117,19 @@ Changes in Element X v0.4.7 (2024-03-26)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Enable the feature "RoomList filters". ([#2603](https://github.com/element-hq/element-x-android/issues/2603))
|
- Enable the feature "RoomList filters". ([#2603](https://github.com/element-hq/element-x-android/issues/2603))
|
||||||
- Enable the feature "Mark as unread" ([#2261](https://github.com/element-hq/element-x-android/issues/2261))
|
- Enable the feature "Mark as unread" ([#2261](https://github.com/element-hq/element-x-android/issues/2261))
|
||||||
- Implement MSC2530 (Body field as media caption) ([#2521](https://github.com/element-hq/element-x-android/issues/2521))
|
- Implement MSC2530 (Body field as media caption) ([#2521](https://github.com/element-hq/element-x-android/issues/2521))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Use user avatar from cache if available. ([#2488](https://github.com/element-hq/element-x-android/issues/2488))
|
- Use user avatar from cache if available. ([#2488](https://github.com/element-hq/element-x-android/issues/2488))
|
||||||
- Update member list after changing member roles and when the room member list is opened. ([#2590](https://github.com/element-hq/element-x-android/issues/2590))
|
- Update member list after changing member roles and when the room member list is opened. ([#2590](https://github.com/element-hq/element-x-android/issues/2590))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Compound: add `BigIcon`, `BigCheckmark` and `PageTitle` components. ([#2574](https://github.com/element-hq/element-x-android/issues/2574))
|
- Compound: add `BigIcon`, `BigCheckmark` and `PageTitle` components. ([#2574](https://github.com/element-hq/element-x-android/issues/2574))
|
||||||
- Remove Welcome screen from the FTUE. ([#2584](https://github.com/element-hq/element-x-android/issues/2584))
|
- Remove Welcome screen from the FTUE. ([#2584](https://github.com/element-hq/element-x-android/issues/2584))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.6 (2024-03-15)
|
Changes in Element X v0.4.6 (2024-03-15)
|
||||||
|
|
@ -76,26 +137,26 @@ Changes in Element X v0.4.6 (2024-03-15)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Admins can now change user roles in rooms. ([#2257](https://github.com/element-hq/element-x-android/issues/2257))
|
- Admins can now change user roles in rooms. ([#2257](https://github.com/element-hq/element-x-android/issues/2257))
|
||||||
- Room member moderation: remove, ban and unban users from a room. ([#2258](https://github.com/element-hq/element-x-android/issues/2258))
|
- Room member moderation: remove, ban and unban users from a room. ([#2258](https://github.com/element-hq/element-x-android/issues/2258))
|
||||||
- Change a room's permissions power levels. ([#2259](https://github.com/element-hq/element-x-android/issues/2259))
|
- Change a room's permissions power levels. ([#2259](https://github.com/element-hq/element-x-android/issues/2259))
|
||||||
- Add state timeline events and notifications for legacy call invites. ([#2485](https://github.com/element-hq/element-x-android/issues/2485))
|
- Add state timeline events and notifications for legacy call invites. ([#2485](https://github.com/element-hq/element-x-android/issues/2485))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Added empty state to banned member list. ([#+add-empty-state-to-banned-members-list](https://github.com/element-hq/element-x-android/issues/+add-empty-state-to-banned-members-list))
|
- Added empty state to banned member list. ([#+add-empty-state-to-banned-members-list](https://github.com/element-hq/element-x-android/issues/+add-empty-state-to-banned-members-list))
|
||||||
- Prevent sending empty messages. ([#995](https://github.com/element-hq/element-x-android/issues/995))
|
- Prevent sending empty messages. ([#995](https://github.com/element-hq/element-x-android/issues/995))
|
||||||
- Use the display name only once in display name change events. The user should be referenced by `userId` instead. ([#2125](https://github.com/element-hq/element-x-android/issues/2125))
|
- Use the display name only once in display name change events. The user should be referenced by `userId` instead. ([#2125](https://github.com/element-hq/element-x-android/issues/2125))
|
||||||
- Hide blocked users list when there are no blocked users. ([#2198](https://github.com/element-hq/element-x-android/issues/2198))
|
- Hide blocked users list when there are no blocked users. ([#2198](https://github.com/element-hq/element-x-android/issues/2198))
|
||||||
- Fix timeline not showing sender info when room is marked as direct but not a 1:1 room. ([#2530](https://github.com/element-hq/element-x-android/issues/2530))
|
- Fix timeline not showing sender info when room is marked as direct but not a 1:1 room. ([#2530](https://github.com/element-hq/element-x-android/issues/2530))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Add `local_time`, `utc_time` and `sdk_sha` params to bug reports so they're easier to investigate. ([#+add-time-and-sdk-sha-params-to-bugreports](https://github.com/element-hq/element-x-android/issues/+add-time-and-sdk-sha-params-to-bugreports))
|
- Add `local_time`, `utc_time` and `sdk_sha` params to bug reports so they're easier to investigate. ([#+add-time-and-sdk-sha-params-to-bugreports](https://github.com/element-hq/element-x-android/issues/+add-time-and-sdk-sha-params-to-bugreports))
|
||||||
- Improve room member list loading times, increase chunk size ([#2322](https://github.com/element-hq/element-x-android/issues/2322))
|
- Improve room member list loading times, increase chunk size ([#2322](https://github.com/element-hq/element-x-android/issues/2322))
|
||||||
- Improve room member list loading UX. ([#2452](https://github.com/element-hq/element-x-android/issues/2452))
|
- Improve room member list loading UX. ([#2452](https://github.com/element-hq/element-x-android/issues/2452))
|
||||||
- Remove the special log level for the Rust SDK read receipts. ([#2511](https://github.com/element-hq/element-x-android/issues/2511))
|
- Remove the special log level for the Rust SDK read receipts. ([#2511](https://github.com/element-hq/element-x-android/issues/2511))
|
||||||
- Track UTD errors. ([#2544](https://github.com/element-hq/element-x-android/issues/2544))
|
- Track UTD errors. ([#2544](https://github.com/element-hq/element-x-android/issues/2544))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.5 (2024-02-28)
|
Changes in Element X v0.4.5 (2024-02-28)
|
||||||
|
|
@ -103,22 +164,22 @@ Changes in Element X v0.4.5 (2024-02-28)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Mark a room or dm as favourite. ([#2208](https://github.com/element-hq/element-x-android/issues/2208))
|
- Mark a room or dm as favourite. ([#2208](https://github.com/element-hq/element-x-android/issues/2208))
|
||||||
- Add moderation to rooms:
|
- Add moderation to rooms:
|
||||||
- Sort member in room member list by powerlevel, display their roles.
|
- Sort member in room member list by powerlevel, display their roles.
|
||||||
- Display banner users in room member list for users with enough power level to ban/unban. ([#2256](https://github.com/element-hq/element-x-android/issues/2256))
|
- Display banner users in room member list for users with enough power level to ban/unban. ([#2256](https://github.com/element-hq/element-x-android/issues/2256))
|
||||||
- MediaViewer : introduce fullscreen and flick to dismiss behavior. ([#2390](https://github.com/element-hq/element-x-android/issues/2390))
|
- MediaViewer : introduce fullscreen and flick to dismiss behavior. ([#2390](https://github.com/element-hq/element-x-android/issues/2390))
|
||||||
- Allow user-installed certificates to be used by the HTTP client ([#2992](https://github.com/element-hq/element-x-android/issues/2992))
|
- Allow user-installed certificates to be used by the HTTP client ([#2992](https://github.com/element-hq/element-x-android/issues/2992))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Do not display empty room list state before the loading one when we still don't have any items ([#+do-not-display-empty-state-before-loading-roomlist](https://github.com/element-hq/element-x-android/issues/+do-not-display-empty-state-before-loading-roomlist))
|
- Do not display empty room list state before the loading one when we still don't have any items ([#+do-not-display-empty-state-before-loading-roomlist](https://github.com/element-hq/element-x-android/issues/+do-not-display-empty-state-before-loading-roomlist))
|
||||||
- Improve how Talkback works with the timeline. Sadly, it's still not 100% working, but there is some issue with the `LazyColumn` using `reverseLayout` that only Google can fix. ([#+improve-accessibility-in-timeline](https://github.com/element-hq/element-x-android/issues/+improve-accessibility-in-timeline))
|
- Improve how Talkback works with the timeline. Sadly, it's still not 100% working, but there is some issue with the `LazyColumn` using `reverseLayout` that only Google can fix. ([#+improve-accessibility-in-timeline](https://github.com/element-hq/element-x-android/issues/+improve-accessibility-in-timeline))
|
||||||
- Add ability to enter a recovery key to verify the session. Also fixes some refresh issues with the verification session state. ([#2421](https://github.com/element-hq/element-x-android/issues/2421))
|
- Add ability to enter a recovery key to verify the session. Also fixes some refresh issues with the verification session state. ([#2421](https://github.com/element-hq/element-x-android/issues/2421))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Provide the current system proxy setting to the Rust SDK. ([#2420](https://github.com/element-hq/element-x-android/issues/2420))
|
- Provide the current system proxy setting to the Rust SDK. ([#2420](https://github.com/element-hq/element-x-android/issues/2420))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.4 (2024-02-15)
|
Changes in Element X v0.4.4 (2024-02-15)
|
||||||
|
|
@ -134,31 +195,31 @@ Changes in Element X v0.4.3 (2024-02-14)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Change "Read receipts" advanced setting used to send private Read Receipt to "Share presence" settings. When disabled, private Read Receipts will be sent, and no typing notification will be sent. Also Read Receipts and typing notifications will not be rendered in the timeline. ([#2241](https://github.com/element-hq/element-x-android/issues/2241))
|
- Change "Read receipts" advanced setting used to send private Read Receipt to "Share presence" settings. When disabled, private Read Receipts will be sent, and no typing notification will be sent. Also Read Receipts and typing notifications will not be rendered in the timeline. ([#2241](https://github.com/element-hq/element-x-android/issues/2241))
|
||||||
- Render typing notifications. ([#2242](https://github.com/element-hq/element-x-android/issues/2242))
|
- Render typing notifications. ([#2242](https://github.com/element-hq/element-x-android/issues/2242))
|
||||||
- Manually mark a room as unread. ([#2261](https://github.com/element-hq/element-x-android/issues/2261))
|
- Manually mark a room as unread. ([#2261](https://github.com/element-hq/element-x-android/issues/2261))
|
||||||
- Add empty state to the room list. ([#2330](https://github.com/element-hq/element-x-android/issues/2330))
|
- Add empty state to the room list. ([#2330](https://github.com/element-hq/element-x-android/issues/2330))
|
||||||
- Allow joining unencrypted video calls in non encrypted rooms. ([#2333](https://github.com/element-hq/element-x-android/issues/2333))
|
- Allow joining unencrypted video calls in non encrypted rooms. ([#2333](https://github.com/element-hq/element-x-android/issues/2333))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix crash after unregistering UnifiedPush distributor ([#2304](https://github.com/element-hq/element-x-android/issues/2304))
|
- Fix crash after unregistering UnifiedPush distributor ([#2304](https://github.com/element-hq/element-x-android/issues/2304))
|
||||||
- Add missing device id to settings screen. ([#2316](https://github.com/element-hq/element-x-android/issues/2316))
|
- Add missing device id to settings screen. ([#2316](https://github.com/element-hq/element-x-android/issues/2316))
|
||||||
- Open the keyboard (and keep it opened) when creating a poll. ([#2329](https://github.com/element-hq/element-x-android/issues/2329))
|
- Open the keyboard (and keep it opened) when creating a poll. ([#2329](https://github.com/element-hq/element-x-android/issues/2329))
|
||||||
- Fix message forwarding after SDK API change related to Timeline intitialization.
|
- Fix message forwarding after SDK API change related to Timeline intitialization.
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Adjusted the login flow buttons so the continue button is always at the same height ([#825](https://github.com/element-hq/element-x-android/issues/825))
|
- Adjusted the login flow buttons so the continue button is always at the same height ([#825](https://github.com/element-hq/element-x-android/issues/825))
|
||||||
- Move migration screen to within the room list ([#2310](https://github.com/element-hq/element-x-android/issues/2310))
|
- Move migration screen to within the room list ([#2310](https://github.com/element-hq/element-x-android/issues/2310))
|
||||||
- Render correctly in reply to data when Event cannot be decrypted or has been redacted ([#2318](https://github.com/element-hq/element-x-android/issues/2318))
|
- Render correctly in reply to data when Event cannot be decrypted or has been redacted ([#2318](https://github.com/element-hq/element-x-android/issues/2318))
|
||||||
- Remove Compose Foundation version pinning workaround. This was done to avoid a bug introduced in the default foundation version used by the material3 library, but that has already been fixed.
|
- Remove Compose Foundation version pinning workaround. This was done to avoid a bug introduced in the default foundation version used by the material3 library, but that has already been fixed.
|
||||||
- Remove `FilterHiddenStateEventsProcessor`, as this is already handled by the Rust SDK.
|
- Remove `FilterHiddenStateEventsProcessor`, as this is already handled by the Rust SDK.
|
||||||
- Remove session preferences on user log out.
|
- Remove session preferences on user log out.
|
||||||
|
|
||||||
Breaking changes 🚨
|
Breaking changes 🚨
|
||||||
-------------------
|
-------------------
|
||||||
- Update Compound icons in the project. Since the icon prefix changed to `ic_compound_` and the `CompoundIcons` helper now contains the vector icons as composable functions.
|
- Update Compound icons in the project. Since the icon prefix changed to `ic_compound_` and the `CompoundIcons` helper now contains the vector icons as composable functions.
|
||||||
|
|
||||||
Changes in Element X v0.4.2 (2024-01-31)
|
Changes in Element X v0.4.2 (2024-01-31)
|
||||||
========================================
|
========================================
|
||||||
|
|
@ -167,31 +228,31 @@ Matrix SDK 🦀 v0.1.95
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Add 'send private read receipts' option in advanced settings ([#2204](https://github.com/element-hq/element-x-android/issues/2204))
|
- Add 'send private read receipts' option in advanced settings ([#2204](https://github.com/element-hq/element-x-android/issues/2204))
|
||||||
- Send typing notification ([#2240](https://github.com/element-hq/element-x-android/issues/2240)). Disabling the sending of typing notification and rendering typing notification will come soon.
|
- Send typing notification ([#2240](https://github.com/element-hq/element-x-android/issues/2240)). Disabling the sending of typing notification and rendering typing notification will come soon.
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Make the room settings screen update automatically when new room info (name, avatar, topic) is available. ([#921](https://github.com/element-hq/element-x-android/issues/921))
|
- Make the room settings screen update automatically when new room info (name, avatar, topic) is available. ([#921](https://github.com/element-hq/element-x-android/issues/921))
|
||||||
- Update timeline items' read receipts when the room members info is loaded. ([#2176](https://github.com/element-hq/element-x-android/issues/2176))
|
- Update timeline items' read receipts when the room members info is loaded. ([#2176](https://github.com/element-hq/element-x-android/issues/2176))
|
||||||
- Edited text message bubbles should resize when edited ([#2260](https://github.com/element-hq/element-x-android/issues/2260))
|
- Edited text message bubbles should resize when edited ([#2260](https://github.com/element-hq/element-x-android/issues/2260))
|
||||||
- Ensure login and password exclude `\n` ([#2263](https://github.com/element-hq/element-x-android/issues/2263))
|
- Ensure login and password exclude `\n` ([#2263](https://github.com/element-hq/element-x-android/issues/2263))
|
||||||
- Room list Ensure the indicators stay grey if the global setting is set to mention only and a regular message is received. ([#2282](https://github.com/element-hq/element-x-android/issues/2282))
|
- Room list Ensure the indicators stay grey if the global setting is set to mention only and a regular message is received. ([#2282](https://github.com/element-hq/element-x-android/issues/2282))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Add a special logging configuration for nightlies so we can get more detailed info for existing issues. ([#+add-special-tracing-configuration-for-nightlies](https://github.com/element-hq/element-x-android/issues/+add-special-tracing-configuration-for-nightlies))
|
- Add a special logging configuration for nightlies so we can get more detailed info for existing issues. ([#+add-special-tracing-configuration-for-nightlies](https://github.com/element-hq/element-x-android/issues/+add-special-tracing-configuration-for-nightlies))
|
||||||
- Try mitigating unexpected logouts by making getting/storing session data use a Mutex for synchronization.
|
- Try mitigating unexpected logouts by making getting/storing session data use a Mutex for synchronization.
|
||||||
Also added some more logs so we can understand exactly where it's failing. ([#+try-mitigating-unexpected-logouts](https://github.com/element-hq/element-x-android/issues/+try-mitigating-unexpected-logouts))
|
Also added some more logs so we can understand exactly where it's failing. ([#+try-mitigating-unexpected-logouts](https://github.com/element-hq/element-x-android/issues/+try-mitigating-unexpected-logouts))
|
||||||
- Upgrade Material3 Compose to `1.2.0-beta02`.
|
- Upgrade Material3 Compose to `1.2.0-beta02`.
|
||||||
There is also a constraint on a transitive Compose Foundation dependency version (1.6.0-beta02) that fixes the timeline scrolling issue. ([#0-beta02](https://github.com/element-hq/element-x-android/issues/0-beta02))
|
There is also a constraint on a transitive Compose Foundation dependency version (1.6.0-beta02) that fixes the timeline scrolling issue. ([#0-beta02](https://github.com/element-hq/element-x-android/issues/0-beta02))
|
||||||
- Disambiguate display name in the timeline. ([#2215](https://github.com/element-hq/element-x-android/issues/2215))
|
- Disambiguate display name in the timeline. ([#2215](https://github.com/element-hq/element-x-android/issues/2215))
|
||||||
- Disambiguate display name in notifications ([#2224](https://github.com/element-hq/element-x-android/issues/2224))
|
- Disambiguate display name in notifications ([#2224](https://github.com/element-hq/element-x-android/issues/2224))
|
||||||
- Remove room creation, self-join of room creator and 'this is the beginning of X' timeline items for DMs. ([#2217](https://github.com/element-hq/element-x-android/issues/2217))
|
- Remove room creation, self-join of room creator and 'this is the beginning of X' timeline items for DMs. ([#2217](https://github.com/element-hq/element-x-android/issues/2217))
|
||||||
- Encrypt databases used by the Rust SDK on Nightly and Debug builds. ([#2219](https://github.com/element-hq/element-x-android/issues/2219))
|
- Encrypt databases used by the Rust SDK on Nightly and Debug builds. ([#2219](https://github.com/element-hq/element-x-android/issues/2219))
|
||||||
- Fallback to UnifiedPush (if available) if the PlayServices are not installed on the device. ([#2248](https://github.com/element-hq/element-x-android/issues/2248))
|
- Fallback to UnifiedPush (if available) if the PlayServices are not installed on the device. ([#2248](https://github.com/element-hq/element-x-android/issues/2248))
|
||||||
- Add "Report a problem" button to the onboarding screen ([#2275](https://github.com/element-hq/element-x-android/issues/2275))
|
- Add "Report a problem" button to the onboarding screen ([#2275](https://github.com/element-hq/element-x-android/issues/2275))
|
||||||
- Add in app logs viewer to the "Report a problem" screen. ([#2276](https://github.com/element-hq/element-x-android/issues/2276))
|
- Add in app logs viewer to the "Report a problem" screen. ([#2276](https://github.com/element-hq/element-x-android/issues/2276))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.1 (2024-01-17)
|
Changes in Element X v0.4.1 (2024-01-17)
|
||||||
|
|
@ -199,35 +260,35 @@ Changes in Element X v0.4.1 (2024-01-17)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Render m.sticker events ([#1949](https://github.com/element-hq/element-x-android/issues/1949))
|
- Render m.sticker events ([#1949](https://github.com/element-hq/element-x-android/issues/1949))
|
||||||
- Add support for sending images from the keyboard ([#1977](https://github.com/element-hq/element-x-android/issues/1977))
|
- Add support for sending images from the keyboard ([#1977](https://github.com/element-hq/element-x-android/issues/1977))
|
||||||
- Added support for MSC4027 (render custom images in reactions) ([#2159](https://github.com/element-hq/element-x-android/issues/2159))
|
- Added support for MSC4027 (render custom images in reactions) ([#2159](https://github.com/element-hq/element-x-android/issues/2159))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix crash sending image with latest Posthog because of an usage of an internal Android method. ([#+crash-sending-image-with-latest-posthog](https://github.com/element-hq/element-x-android/issues/+crash-sending-image-with-latest-posthog))
|
- Fix crash sending image with latest Posthog because of an usage of an internal Android method. ([#+crash-sending-image-with-latest-posthog](https://github.com/element-hq/element-x-android/issues/+crash-sending-image-with-latest-posthog))
|
||||||
- Make sure the media viewer tries the main url first (if not empty) then the thumbnail url and then not open if both are missing instead of failing with an error dialog ([#1949](https://github.com/element-hq/element-x-android/issues/1949))
|
- Make sure the media viewer tries the main url first (if not empty) then the thumbnail url and then not open if both are missing instead of failing with an error dialog ([#1949](https://github.com/element-hq/element-x-android/issues/1949))
|
||||||
- Fix room transition animation happens twice. ([#2084](https://github.com/element-hq/element-x-android/issues/2084))
|
- Fix room transition animation happens twice. ([#2084](https://github.com/element-hq/element-x-android/issues/2084))
|
||||||
- Disable ability to send reaction if the user does not have the permission to. ([#2093](https://github.com/element-hq/element-x-android/issues/2093))
|
- Disable ability to send reaction if the user does not have the permission to. ([#2093](https://github.com/element-hq/element-x-android/issues/2093))
|
||||||
- Trim whitespace at the end of messages to ensure we render the right content. ([#2099](https://github.com/element-hq/element-x-android/issues/2099))
|
- Trim whitespace at the end of messages to ensure we render the right content. ([#2099](https://github.com/element-hq/element-x-android/issues/2099))
|
||||||
- Fix crashes in room list when the last message for a room was an extremely long one (several thousands of characters) with no line breaks. ([#2105](https://github.com/element-hq/element-x-android/issues/2105))
|
- Fix crashes in room list when the last message for a room was an extremely long one (several thousands of characters) with no line breaks. ([#2105](https://github.com/element-hq/element-x-android/issues/2105))
|
||||||
- Disable rasterisation of Vector XMLs, which was causing crashes on API 23. ([#2124](https://github.com/element-hq/element-x-android/issues/2124))
|
- Disable rasterisation of Vector XMLs, which was causing crashes on API 23. ([#2124](https://github.com/element-hq/element-x-android/issues/2124))
|
||||||
- Use `SubomposeLayout` for `ContentAvoidingLayout` to prevent wrong measurements in the layout process, leading to cut-off text messages in the timeline. ([#2155](https://github.com/element-hq/element-x-android/issues/2155))
|
- Use `SubomposeLayout` for `ContentAvoidingLayout` to prevent wrong measurements in the layout process, leading to cut-off text messages in the timeline. ([#2155](https://github.com/element-hq/element-x-android/issues/2155))
|
||||||
- Improve rendering of voice messages in the timeline in large displays ([#2156](https://github.com/element-hq/element-x-android/issues/2156))
|
- Improve rendering of voice messages in the timeline in large displays ([#2156](https://github.com/element-hq/element-x-android/issues/2156))
|
||||||
- Fix no indication that user list is loading when inviting to room. ([#2172](https://github.com/element-hq/element-x-android/issues/2172))
|
- Fix no indication that user list is loading when inviting to room. ([#2172](https://github.com/element-hq/element-x-android/issues/2172))
|
||||||
- Hide keyboard when tapping on a message in the timeline. ([#2182](https://github.com/element-hq/element-x-android/issues/2182))
|
- Hide keyboard when tapping on a message in the timeline. ([#2182](https://github.com/element-hq/element-x-android/issues/2182))
|
||||||
- Mention selector gets stuck when quickly deleting the prompt. ([#2192](https://github.com/element-hq/element-x-android/issues/2192))
|
- Mention selector gets stuck when quickly deleting the prompt. ([#2192](https://github.com/element-hq/element-x-android/issues/2192))
|
||||||
- Hide verbose state events from the timeline ([#2216](https://github.com/element-hq/element-x-android/issues/2216))
|
- Hide verbose state events from the timeline ([#2216](https://github.com/element-hq/element-x-android/issues/2216))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Only apply `com.autonomousapps.dependency-analysis` plugin in those modules that need it. ([#+only-apply-dependency-analysis-plugin-where-needed](https://github.com/element-hq/element-x-android/issues/+only-apply-dependency-analysis-plugin-where-needed))
|
- Only apply `com.autonomousapps.dependency-analysis` plugin in those modules that need it. ([#+only-apply-dependency-analysis-plugin-where-needed](https://github.com/element-hq/element-x-android/issues/+only-apply-dependency-analysis-plugin-where-needed))
|
||||||
- Migrate to Kover 0.7.X ([#1782](https://github.com/element-hq/element-x-android/issues/1782))
|
- Migrate to Kover 0.7.X ([#1782](https://github.com/element-hq/element-x-android/issues/1782))
|
||||||
- Remove extra logout screen. ([#2072](https://github.com/element-hq/element-x-android/issues/2072))
|
- Remove extra logout screen. ([#2072](https://github.com/element-hq/element-x-android/issues/2072))
|
||||||
- Handle `MembershipChange.NONE` rendering in the timeline. ([#2102](https://github.com/element-hq/element-x-android/issues/2102))
|
- Handle `MembershipChange.NONE` rendering in the timeline. ([#2102](https://github.com/element-hq/element-x-android/issues/2102))
|
||||||
- Remove extra previews for timestamp view with 'document' case ([#2127](https://github.com/element-hq/element-x-android/issues/2127))
|
- Remove extra previews for timestamp view with 'document' case ([#2127](https://github.com/element-hq/element-x-android/issues/2127))
|
||||||
- Bump AGP version to 8.2.0 ([#2142](https://github.com/element-hq/element-x-android/issues/2142))
|
- Bump AGP version to 8.2.0 ([#2142](https://github.com/element-hq/element-x-android/issues/2142))
|
||||||
- Replace 'leave room' text with 'leave conversation' for DMs. ([#2218](https://github.com/element-hq/element-x-android/issues/2218))
|
- Replace 'leave room' text with 'leave conversation' for DMs. ([#2218](https://github.com/element-hq/element-x-android/issues/2218))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.4.0 (2023-12-22)
|
Changes in Element X v0.4.0 (2023-12-22)
|
||||||
|
|
@ -235,75 +296,75 @@ Changes in Element X v0.4.0 (2023-12-22)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Use the RTE library `TextView` to render text events in the timeline. Add support for mention pills - with no interaction yet. ([#1433](https://github.com/element-hq/element-x-android/issues/1433))
|
- Use the RTE library `TextView` to render text events in the timeline. Add support for mention pills - with no interaction yet. ([#1433](https://github.com/element-hq/element-x-android/issues/1433))
|
||||||
- Tapping on a user mention pill opens their profile. ([#1448](https://github.com/element-hq/element-x-android/issues/1448))
|
- Tapping on a user mention pill opens their profile. ([#1448](https://github.com/element-hq/element-x-android/issues/1448))
|
||||||
- Display different notifications for mentions. ([#1451](https://github.com/element-hq/element-x-android/issues/1451))
|
- Display different notifications for mentions. ([#1451](https://github.com/element-hq/element-x-android/issues/1451))
|
||||||
- Reply to a poll ([#1848](https://github.com/element-hq/element-x-android/issues/1848))
|
- Reply to a poll ([#1848](https://github.com/element-hq/element-x-android/issues/1848))
|
||||||
- Add plain text representation of messages ([#1850](https://github.com/element-hq/element-x-android/issues/1850))
|
- Add plain text representation of messages ([#1850](https://github.com/element-hq/element-x-android/issues/1850))
|
||||||
- Allow polls to be edited when they have not been voted on ([#1869](https://github.com/element-hq/element-x-android/issues/1869))
|
- Allow polls to be edited when they have not been voted on ([#1869](https://github.com/element-hq/element-x-android/issues/1869))
|
||||||
- Scroll to end of timeline when sending a new message. ([#1877](https://github.com/element-hq/element-x-android/issues/1877))
|
- Scroll to end of timeline when sending a new message. ([#1877](https://github.com/element-hq/element-x-android/issues/1877))
|
||||||
- Confirm back navigation when editing a poll only if the poll was changed ([#1886](https://github.com/element-hq/element-x-android/issues/1886))
|
- Confirm back navigation when editing a poll only if the poll was changed ([#1886](https://github.com/element-hq/element-x-android/issues/1886))
|
||||||
- Add option to delete a poll while editing the poll ([#1895](https://github.com/element-hq/element-x-android/issues/1895))
|
- Add option to delete a poll while editing the poll ([#1895](https://github.com/element-hq/element-x-android/issues/1895))
|
||||||
- Open room member avatar when you click on it inside the member details screen. ([#1907](https://github.com/element-hq/element-x-android/issues/1907))
|
- Open room member avatar when you click on it inside the member details screen. ([#1907](https://github.com/element-hq/element-x-android/issues/1907))
|
||||||
- Poll history of a room is now accessible from the room details screen. ([#2014](https://github.com/element-hq/element-x-android/issues/2014))
|
- Poll history of a room is now accessible from the room details screen. ([#2014](https://github.com/element-hq/element-x-android/issues/2014))
|
||||||
- Always close the invite list screen when there is no more invite. ([#2022](https://github.com/element-hq/element-x-android/issues/2022))
|
- Always close the invite list screen when there is no more invite. ([#2022](https://github.com/element-hq/element-x-android/issues/2022))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix see room in the room list after leaving it. ([#1006](https://github.com/element-hq/element-x-android/issues/1006))
|
- Fix see room in the room list after leaving it. ([#1006](https://github.com/element-hq/element-x-android/issues/1006))
|
||||||
- Adjust mention pills font weight and horizontal padding ([#1449](https://github.com/element-hq/element-x-android/issues/1449))
|
- Adjust mention pills font weight and horizontal padding ([#1449](https://github.com/element-hq/element-x-android/issues/1449))
|
||||||
- Font size in 'All Chats' header was changing mid-animation. ([#1572](https://github.com/element-hq/element-x-android/issues/1572))
|
- Font size in 'All Chats' header was changing mid-animation. ([#1572](https://github.com/element-hq/element-x-android/issues/1572))
|
||||||
- Accessibility: do not read initial used for avatar out loud. ([#1864](https://github.com/element-hq/element-x-android/issues/1864))
|
- Accessibility: do not read initial used for avatar out loud. ([#1864](https://github.com/element-hq/element-x-android/issues/1864))
|
||||||
- Use the right avatar for DMs in DM rooms ([#1912](https://github.com/element-hq/element-x-android/issues/1912))
|
- Use the right avatar for DMs in DM rooms ([#1912](https://github.com/element-hq/element-x-android/issues/1912))
|
||||||
- Fix scaling of timeline images: don't crop, don't set min/max aspect ratio values. ([#1940](https://github.com/element-hq/element-x-android/issues/1940))
|
- Fix scaling of timeline images: don't crop, don't set min/max aspect ratio values. ([#1940](https://github.com/element-hq/element-x-android/issues/1940))
|
||||||
- Fix rendering of user name with vertical text by clipping the text. ([#1950](https://github.com/element-hq/element-x-android/issues/1950))
|
- Fix rendering of user name with vertical text by clipping the text. ([#1950](https://github.com/element-hq/element-x-android/issues/1950))
|
||||||
- Do not render `roomId` if the room has no canonical alias. ([#1970](https://github.com/element-hq/element-x-android/issues/1970))
|
- Do not render `roomId` if the room has no canonical alias. ([#1970](https://github.com/element-hq/element-x-android/issues/1970))
|
||||||
- Fix avatar not displayed in notification when the app is not in background ([#1991](https://github.com/element-hq/element-x-android/issues/1991))
|
- Fix avatar not displayed in notification when the app is not in background ([#1991](https://github.com/element-hq/element-x-android/issues/1991))
|
||||||
- Fix wording in room invite members view: `Send` -> `Invite`. ([#2037](https://github.com/element-hq/element-x-android/issues/2037))
|
- Fix wording in room invite members view: `Send` -> `Invite`. ([#2037](https://github.com/element-hq/element-x-android/issues/2037))
|
||||||
- Timestamp positioning was broken, specially for edited messages. ([#2060](https://github.com/element-hq/element-x-android/issues/2060))
|
- Timestamp positioning was broken, specially for edited messages. ([#2060](https://github.com/element-hq/element-x-android/issues/2060))
|
||||||
- Emojis in custom reaction bottom sheet are too tiny. ([#2066](https://github.com/element-hq/element-x-android/issues/2066))
|
- Emojis in custom reaction bottom sheet are too tiny. ([#2066](https://github.com/element-hq/element-x-android/issues/2066))
|
||||||
- Set a default power level to join calls. Also, create new rooms taking this power level into account.
|
- Set a default power level to join calls. Also, create new rooms taking this power level into account.
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Add a warning for 'mentions and keywords only' notification option if your homeserver does not support it ([#1749](https://github.com/element-hq/element-x-android/issues/1749))
|
- Add a warning for 'mentions and keywords only' notification option if your homeserver does not support it ([#1749](https://github.com/element-hq/element-x-android/issues/1749))
|
||||||
- Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/element-hq/compound-android). ([#1833](https://github.com/element-hq/element-x-android/issues/1833))
|
- Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/element-hq/compound-android). ([#1833](https://github.com/element-hq/element-x-android/issues/1833))
|
||||||
- Update poll icons from Compound ([#1849](https://github.com/element-hq/element-x-android/issues/1849))
|
- Update poll icons from Compound ([#1849](https://github.com/element-hq/element-x-android/issues/1849))
|
||||||
- Add ability to see the room avatar in the media viewer. ([#1918](https://github.com/element-hq/element-x-android/issues/1918))
|
- Add ability to see the room avatar in the media viewer. ([#1918](https://github.com/element-hq/element-x-android/issues/1918))
|
||||||
- RoomList: introduce incremental loading to improve performances. ([#1920](https://github.com/element-hq/element-x-android/issues/1920))
|
- RoomList: introduce incremental loading to improve performances. ([#1920](https://github.com/element-hq/element-x-android/issues/1920))
|
||||||
- Add toggle in the notification settings to disable notifications for room invites. ([#1944](https://github.com/element-hq/element-x-android/issues/1944))
|
- Add toggle in the notification settings to disable notifications for room invites. ([#1944](https://github.com/element-hq/element-x-android/issues/1944))
|
||||||
- Update rendering of Emojis displayed during verification. ([#1965](https://github.com/element-hq/element-x-android/issues/1965))
|
- Update rendering of Emojis displayed during verification. ([#1965](https://github.com/element-hq/element-x-android/issues/1965))
|
||||||
- Hide sender info in direct rooms ([#1979](https://github.com/element-hq/element-x-android/issues/1979))
|
- Hide sender info in direct rooms ([#1979](https://github.com/element-hq/element-x-android/issues/1979))
|
||||||
- Render images in Notification ([#1991](https://github.com/element-hq/element-x-android/issues/1991))
|
- Render images in Notification ([#1991](https://github.com/element-hq/element-x-android/issues/1991))
|
||||||
- Only process content.json from Localazy. ([#2031](https://github.com/element-hq/element-x-android/issues/2031))
|
- Only process content.json from Localazy. ([#2031](https://github.com/element-hq/element-x-android/issues/2031))
|
||||||
- Always show user avatar in message action sheet ([#2032](https://github.com/element-hq/element-x-android/issues/2032))
|
- Always show user avatar in message action sheet ([#2032](https://github.com/element-hq/element-x-android/issues/2032))
|
||||||
- Hide room list dropdown menu. ([#2062](https://github.com/element-hq/element-x-android/issues/2062))
|
- Hide room list dropdown menu. ([#2062](https://github.com/element-hq/element-x-android/issues/2062))
|
||||||
- Enable Chat backup, Mentions and Read Receipt in release. ([#2087](https://github.com/element-hq/element-x-android/issues/2087))
|
- Enable Chat backup, Mentions and Read Receipt in release. ([#2087](https://github.com/element-hq/element-x-android/issues/2087))
|
||||||
- Make most code used in Compose from `:libraries:matrix` and derived classes Immutable or Stable.
|
- Make most code used in Compose from `:libraries:matrix` and derived classes Immutable or Stable.
|
||||||
|
|
||||||
Changes in Element X v0.3.2 (2023-11-22)
|
Changes in Element X v0.3.2 (2023-11-22)
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Add ongoing call indicator to rooms lists items. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
|
- Add ongoing call indicator to rooms lists items. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
|
||||||
- Add support for typing mentions in the message composer. ([#1453](https://github.com/element-hq/element-x-android/issues/1453))
|
- Add support for typing mentions in the message composer. ([#1453](https://github.com/element-hq/element-x-android/issues/1453))
|
||||||
- Add intentional mentions to messages. This needs to be enabled in developer options since it's disabled by default. ([#1591](https://github.com/element-hq/element-x-android/issues/1591))
|
- Add intentional mentions to messages. This needs to be enabled in developer options since it's disabled by default. ([#1591](https://github.com/element-hq/element-x-android/issues/1591))
|
||||||
- Update voice message recording behaviour. Instead of holding the record button, users can now tap the record button to start recording and tap again to stop recording. ([#1784](https://github.com/element-hq/element-x-android/issues/1784))
|
- Update voice message recording behaviour. Instead of holding the record button, users can now tap the record button to start recording and tap again to stop recording. ([#1784](https://github.com/element-hq/element-x-android/issues/1784))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Always ensure media temp dir exists ([#1790](https://github.com/element-hq/element-x-android/issues/1790))
|
- Always ensure media temp dir exists ([#1790](https://github.com/element-hq/element-x-android/issues/1790))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Update icons and move away from `PreferenceText` components. ([#1718](https://github.com/element-hq/element-x-android/issues/1718))
|
- Update icons and move away from `PreferenceText` components. ([#1718](https://github.com/element-hq/element-x-android/issues/1718))
|
||||||
- Add item "This is the beginning of..." at the beginning of the timeline. ([#1801](https://github.com/element-hq/element-x-android/issues/1801))
|
- Add item "This is the beginning of..." at the beginning of the timeline. ([#1801](https://github.com/element-hq/element-x-android/issues/1801))
|
||||||
- LockScreen : rework LoggedInFlowNode and back management when locked. ([#1806](https://github.com/element-hq/element-x-android/issues/1806))
|
- LockScreen : rework LoggedInFlowNode and back management when locked. ([#1806](https://github.com/element-hq/element-x-android/issues/1806))
|
||||||
- Suppress usage of removeTimeline method. ([#1824](https://github.com/element-hq/element-x-android/issues/1824))
|
- Suppress usage of removeTimeline method. ([#1824](https://github.com/element-hq/element-x-android/issues/1824))
|
||||||
- Remove Element Call feature flag, it's now always enabled.
|
- Remove Element Call feature flag, it's now always enabled.
|
||||||
- Reverted the EC base URL to `https://call.element.io`.
|
- Reverted the EC base URL to `https://call.element.io`.
|
||||||
- Moved the option to override this URL to developer settings from advanced settings.
|
- Moved the option to override this URL to developer settings from advanced settings.
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.3.1 (2023-11-09)
|
Changes in Element X v0.3.1 (2023-11-09)
|
||||||
|
|
@ -311,16 +372,16 @@ Changes in Element X v0.3.1 (2023-11-09)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Chat backup is still under a feature flag, but when enabled, user can enter their recovery key (it's also possible to input a passphrase) to unlock the encrypted room history. ([#1770](https://github.com/element-hq/element-x-android/pull/1770))
|
- Chat backup is still under a feature flag, but when enabled, user can enter their recovery key (it's also possible to input a passphrase) to unlock the encrypted room history. ([#1770](https://github.com/element-hq/element-x-android/pull/1770))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Improve confusing text in the 'ready to start verification' screen. ([#879](https://github.com/element-hq/element-x-android/issues/879))
|
- Improve confusing text in the 'ready to start verification' screen. ([#879](https://github.com/element-hq/element-x-android/issues/879))
|
||||||
- Message composer wasn't resized when selecting a several lines message to reply to, then a single line one. ([#1560](https://github.com/element-hq/element-x-android/issues/1560))
|
- Message composer wasn't resized when selecting a several lines message to reply to, then a single line one. ([#1560](https://github.com/element-hq/element-x-android/issues/1560))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- PIN: Set lock grace period to 0. ([#1732](https://github.com/element-hq/element-x-android/issues/1732))
|
- PIN: Set lock grace period to 0. ([#1732](https://github.com/element-hq/element-x-android/issues/1732))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.3.0 (2023-10-31)
|
Changes in Element X v0.3.0 (2023-10-31)
|
||||||
|
|
@ -328,24 +389,24 @@ Changes in Element X v0.3.0 (2023-10-31)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Element Call: change the 'join call' button in a chat room when there's an active call. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
|
- Element Call: change the 'join call' button in a chat room when there's an active call. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
|
||||||
- Mentions: add mentions suggestion view in RTE ([#1452](https://github.com/element-hq/element-x-android/issues/1452))
|
- Mentions: add mentions suggestion view in RTE ([#1452](https://github.com/element-hq/element-x-android/issues/1452))
|
||||||
- Record and send voice messages ([#1596](https://github.com/element-hq/element-x-android/issues/1596))
|
- Record and send voice messages ([#1596](https://github.com/element-hq/element-x-android/issues/1596))
|
||||||
- Enable voice messages for all users ([#1669](https://github.com/element-hq/element-x-android/issues/1669))
|
- Enable voice messages for all users ([#1669](https://github.com/element-hq/element-x-android/issues/1669))
|
||||||
- Receive and play a voice message ([#2084](https://github.com/element-hq/element-x-android/issues/2084))
|
- Receive and play a voice message ([#2084](https://github.com/element-hq/element-x-android/issues/2084))
|
||||||
- Enable Element Call integration in rooms by default, fix several issues when creating or joining calls.
|
- Enable Element Call integration in rooms by default, fix several issues when creating or joining calls.
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Group fallback notification to avoid having plenty of them displayed. ([#994](https://github.com/element-hq/element-x-android/issues/994))
|
- Group fallback notification to avoid having plenty of them displayed. ([#994](https://github.com/element-hq/element-x-android/issues/994))
|
||||||
- Hide keyboard when exiting the chat room screen. ([#1375](https://github.com/element-hq/element-x-android/issues/1375))
|
- Hide keyboard when exiting the chat room screen. ([#1375](https://github.com/element-hq/element-x-android/issues/1375))
|
||||||
- Always register the pusher when application starts ([#1481](https://github.com/element-hq/element-x-android/issues/1481))
|
- Always register the pusher when application starts ([#1481](https://github.com/element-hq/element-x-android/issues/1481))
|
||||||
- Ensure screen does not turn off when playing a video ([#1519](https://github.com/element-hq/element-x-android/issues/1519))
|
- Ensure screen does not turn off when playing a video ([#1519](https://github.com/element-hq/element-x-android/issues/1519))
|
||||||
- Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/element-hq/element-x-android/issues/1617))
|
- Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/element-hq/element-x-android/issues/1617))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Remove usage of blocking methods. ([#1563](https://github.com/element-hq/element-x-android/issues/1563))
|
- Remove usage of blocking methods. ([#1563](https://github.com/element-hq/element-x-android/issues/1563))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.2.4 (2023-10-12)
|
Changes in Element X v0.2.4 (2023-10-12)
|
||||||
|
|
@ -353,20 +414,20 @@ Changes in Element X v0.2.4 (2023-10-12)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- [Rich text editor] Add full screen mode ([#1447](https://github.com/element-hq/element-x-android/issues/1447))
|
- [Rich text editor] Add full screen mode ([#1447](https://github.com/element-hq/element-x-android/issues/1447))
|
||||||
- Improve rendering of m.emote. ([#1497](https://github.com/element-hq/element-x-android/issues/1497))
|
- Improve rendering of m.emote. ([#1497](https://github.com/element-hq/element-x-android/issues/1497))
|
||||||
- Improve deleted session behavior. ([#1520](https://github.com/element-hq/element-x-android/issues/1520))
|
- Improve deleted session behavior. ([#1520](https://github.com/element-hq/element-x-android/issues/1520))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- WebP images can't be sent as media. ([#1483](https://github.com/element-hq/element-x-android/issues/1483))
|
- WebP images can't be sent as media. ([#1483](https://github.com/element-hq/element-x-android/issues/1483))
|
||||||
- Fix back button not working in bottom sheets. ([#1517](https://github.com/element-hq/element-x-android/issues/1517))
|
- Fix back button not working in bottom sheets. ([#1517](https://github.com/element-hq/element-x-android/issues/1517))
|
||||||
- Render body of unknown msgtype in the timeline and in the room list ([#1539](https://github.com/element-hq/element-x-android/issues/1539))
|
- Render body of unknown msgtype in the timeline and in the room list ([#1539](https://github.com/element-hq/element-x-android/issues/1539))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Room : makes subscribeToSync/unsubscribeFromSync suspendable. ([#1457](https://github.com/element-hq/element-x-android/issues/1457))
|
- Room : makes subscribeToSync/unsubscribeFromSync suspendable. ([#1457](https://github.com/element-hq/element-x-android/issues/1457))
|
||||||
- Add some Konsist tests. ([#1526](https://github.com/element-hq/element-x-android/issues/1526))
|
- Add some Konsist tests. ([#1526](https://github.com/element-hq/element-x-android/issues/1526))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.2.3 (2023-09-27)
|
Changes in Element X v0.2.3 (2023-09-27)
|
||||||
|
|
@ -374,12 +435,12 @@ Changes in Element X v0.2.3 (2023-09-27)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Handle installation of Apks from the media viewer. ([#1432](https://github.com/element-hq/element-x-android/pull/1432))
|
- Handle installation of Apks from the media viewer. ([#1432](https://github.com/element-hq/element-x-android/pull/1432))
|
||||||
- Integrate SDK 0.1.58 ([#1437](https://github.com/element-hq/element-x-android/pull/1437))
|
- Integrate SDK 0.1.58 ([#1437](https://github.com/element-hq/element-x-android/pull/1437))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Element call: add custom parameters to Element Call urls. ([#1434](https://github.com/element-hq/element-x-android/issues/1434))
|
- Element call: add custom parameters to Element Call urls. ([#1434](https://github.com/element-hq/element-x-android/issues/1434))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.2.2 (2023-09-21)
|
Changes in Element X v0.2.2 (2023-09-21)
|
||||||
|
|
@ -387,8 +448,8 @@ Changes in Element X v0.2.2 (2023-09-21)
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/element-hq/element-x-android/issues/1323))
|
- Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/element-hq/element-x-android/issues/1323))
|
||||||
- Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/element-hq/element-x-android/issues/1395))
|
- Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/element-hq/element-x-android/issues/1395))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.2.1 (2023-09-20)
|
Changes in Element X v0.2.1 (2023-09-20)
|
||||||
|
|
@ -396,19 +457,19 @@ Changes in Element X v0.2.1 (2023-09-20)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Bump Rust SDK to `v0.1.56`
|
- Bump Rust SDK to `v0.1.56`
|
||||||
- [Rich text editor] Add link support to rich text editor ([#1309](https://github.com/element-hq/element-x-android/issues/1309))
|
- [Rich text editor] Add link support to rich text editor ([#1309](https://github.com/element-hq/element-x-android/issues/1309))
|
||||||
- Let the SDK figure the best scheme given an homeserver URL (thus allowing HTTP homeservers) ([#1382](https://github.com/element-hq/element-x-android/issues/1382))
|
- Let the SDK figure the best scheme given an homeserver URL (thus allowing HTTP homeservers) ([#1382](https://github.com/element-hq/element-x-android/issues/1382))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix ANR on RoomList when notification settings change. ([#1370](https://github.com/element-hq/element-x-android/issues/1370))
|
- Fix ANR on RoomList when notification settings change. ([#1370](https://github.com/element-hq/element-x-android/issues/1370))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Element Call: support scheme `io.element.call` ([#1377](https://github.com/element-hq/element-x-android/issues/1377))
|
- Element Call: support scheme `io.element.call` ([#1377](https://github.com/element-hq/element-x-android/issues/1377))
|
||||||
- [DI] Rework how dagger components are created and provided. ([#1378](https://github.com/element-hq/element-x-android/issues/1378))
|
- [DI] Rework how dagger components are created and provided. ([#1378](https://github.com/element-hq/element-x-android/issues/1378))
|
||||||
- Remove usage of async-uniffi as it leads to a deadlocks and memory leaks. ([#1381](https://github.com/element-hq/element-x-android/issues/1381))
|
- Remove usage of async-uniffi as it leads to a deadlocks and memory leaks. ([#1381](https://github.com/element-hq/element-x-android/issues/1381))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.2.0 (2023-09-18)
|
Changes in Element X v0.2.0 (2023-09-18)
|
||||||
|
|
@ -416,38 +477,38 @@ Changes in Element X v0.2.0 (2023-09-18)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Bump Rust SDK to `v0.1.54`
|
- Bump Rust SDK to `v0.1.54`
|
||||||
- Add a "Mute" shortcut icon and a "Notifications" section in the room details screen ([#506](https://github.com/element-hq/element-x-android/issues/506))
|
- Add a "Mute" shortcut icon and a "Notifications" section in the room details screen ([#506](https://github.com/element-hq/element-x-android/issues/506))
|
||||||
- Add a notification permission screen to the initial flow. ([#897](https://github.com/element-hq/element-x-android/issues/897))
|
- Add a notification permission screen to the initial flow. ([#897](https://github.com/element-hq/element-x-android/issues/897))
|
||||||
- Integrate Element Call into EX by embedding a call in a WebView. ([#1300](https://github.com/element-hq/element-x-android/issues/1300))
|
- Integrate Element Call into EX by embedding a call in a WebView. ([#1300](https://github.com/element-hq/element-x-android/issues/1300))
|
||||||
- Implement Bloom effect modifier. ([#1217](https://github.com/element-hq/element-x-android/issues/1217))
|
- Implement Bloom effect modifier. ([#1217](https://github.com/element-hq/element-x-android/issues/1217))
|
||||||
- Set color on display name and default avatar in the timeline. ([#1224](https://github.com/element-hq/element-x-android/issues/1224))
|
- Set color on display name and default avatar in the timeline. ([#1224](https://github.com/element-hq/element-x-android/issues/1224))
|
||||||
- Display a thread decorator in timeline so we know when a message is coming from a thread. ([#1236](https://github.com/element-hq/element-x-android/issues/1236))
|
- Display a thread decorator in timeline so we know when a message is coming from a thread. ([#1236](https://github.com/element-hq/element-x-android/issues/1236))
|
||||||
- [Rich text editor] Integrate rich text editor library. Note that markdown is now not supported and further formatting support will be introduced through the rich text editor. ([#1172](https://github.com/element-hq/element-x-android/issues/1172))
|
- [Rich text editor] Integrate rich text editor library. Note that markdown is now not supported and further formatting support will be introduced through the rich text editor. ([#1172](https://github.com/element-hq/element-x-android/issues/1172))
|
||||||
- [Rich text editor] Add formatting menu (accessible via the '+' button) ([#1261](https://github.com/element-hq/element-x-android/issues/1261))
|
- [Rich text editor] Add formatting menu (accessible via the '+' button) ([#1261](https://github.com/element-hq/element-x-android/issues/1261))
|
||||||
- [Rich text editor] Add feature flag for rich text editor. Markdown support can now be enabled by disabling the rich text editor. ([#1289](https://github.com/element-hq/element-x-android/issues/1289))
|
- [Rich text editor] Add feature flag for rich text editor. Markdown support can now be enabled by disabling the rich text editor. ([#1289](https://github.com/element-hq/element-x-android/issues/1289))
|
||||||
- [Rich text editor] Update design ([#1332](https://github.com/element-hq/element-x-android/issues/1332))
|
- [Rich text editor] Update design ([#1332](https://github.com/element-hq/element-x-android/issues/1332))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Make links in room topic clickable ([#612](https://github.com/element-hq/element-x-android/issues/612))
|
- Make links in room topic clickable ([#612](https://github.com/element-hq/element-x-android/issues/612))
|
||||||
- Reply action: harmonize conditions in bottom sheet and swipe to reply. ([#1173](https://github.com/element-hq/element-x-android/issues/1173))
|
- Reply action: harmonize conditions in bottom sheet and swipe to reply. ([#1173](https://github.com/element-hq/element-x-android/issues/1173))
|
||||||
- Fix system bar color after login on light theme. ([#1222](https://github.com/element-hq/element-x-android/issues/1222))
|
- Fix system bar color after login on light theme. ([#1222](https://github.com/element-hq/element-x-android/issues/1222))
|
||||||
- Fix long click on simple formatted messages ([#1232](https://github.com/element-hq/element-x-android/issues/1232))
|
- Fix long click on simple formatted messages ([#1232](https://github.com/element-hq/element-x-android/issues/1232))
|
||||||
- Enable polls in release build. ([#1241](https://github.com/element-hq/element-x-android/issues/1241))
|
- Enable polls in release build. ([#1241](https://github.com/element-hq/element-x-android/issues/1241))
|
||||||
- Fix top padding in room list when app is opened in offline mode. ([#1297](https://github.com/element-hq/element-x-android/issues/1297))
|
- Fix top padding in room list when app is opened in offline mode. ([#1297](https://github.com/element-hq/element-x-android/issues/1297))
|
||||||
- [Rich text editor] Fix 'text formatting' option only partially visible ([#1335](https://github.com/element-hq/element-x-android/issues/1335))
|
- [Rich text editor] Fix 'text formatting' option only partially visible ([#1335](https://github.com/element-hq/element-x-android/issues/1335))
|
||||||
- [Rich text editor] Ensure keyboard opens for reply and text formatting modes ([#1337](https://github.com/element-hq/element-x-android/issues/1337))
|
- [Rich text editor] Ensure keyboard opens for reply and text formatting modes ([#1337](https://github.com/element-hq/element-x-android/issues/1337))
|
||||||
- [Rich text editor] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/element-hq/element-x-android/issues/1347))
|
- [Rich text editor] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/element-hq/element-x-android/issues/1347))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Add a sub-screen "Notifications" in the existing application Settings ([#510](https://github.com/element-hq/element-x-android/issues/510))
|
- Add a sub-screen "Notifications" in the existing application Settings ([#510](https://github.com/element-hq/element-x-android/issues/510))
|
||||||
- Exclude some groups related to analytics to be included. ([#1191](https://github.com/element-hq/element-x-android/issues/1191))
|
- Exclude some groups related to analytics to be included. ([#1191](https://github.com/element-hq/element-x-android/issues/1191))
|
||||||
- Use the new SyncIndicator API. ([#1244](https://github.com/element-hq/element-x-android/issues/1244))
|
- Use the new SyncIndicator API. ([#1244](https://github.com/element-hq/element-x-android/issues/1244))
|
||||||
- Improve RoomSummary mapping by using RoomInfo. ([#1251](https://github.com/element-hq/element-x-android/issues/1251))
|
- Improve RoomSummary mapping by using RoomInfo. ([#1251](https://github.com/element-hq/element-x-android/issues/1251))
|
||||||
- Ensure Posthog data are sent to "https://posthog.element.io" ([#1269](https://github.com/element-hq/element-x-android/issues/1269))
|
- Ensure Posthog data are sent to "https://posthog.element.io" ([#1269](https://github.com/element-hq/element-x-android/issues/1269))
|
||||||
- New app icon, with monochrome support. ([#1363](https://github.com/element-hq/element-x-android/issues/1363))
|
- New app icon, with monochrome support. ([#1363](https://github.com/element-hq/element-x-android/issues/1363))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.1.6 (2023-09-04)
|
Changes in Element X v0.1.6 (2023-09-04)
|
||||||
|
|
@ -455,22 +516,22 @@ Changes in Element X v0.1.6 (2023-09-04)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Enable the Polls feature. Allows to create, view, vote and end polls. ([#1196](https://github.com/element-hq/element-x-android/issues/1196))
|
- Enable the Polls feature. Allows to create, view, vote and end polls. ([#1196](https://github.com/element-hq/element-x-android/issues/1196))
|
||||||
- Create poll. ([#1143](https://github.com/element-hq/element-x-android/issues/1143))
|
- Create poll. ([#1143](https://github.com/element-hq/element-x-android/issues/1143))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Ensure notification for Event from encrypted room get decrypted content. ([#1178](https://github.com/element-hq/element-x-android/issues/1178))
|
- Ensure notification for Event from encrypted room get decrypted content. ([#1178](https://github.com/element-hq/element-x-android/issues/1178))
|
||||||
- Make sure Snackbars are only displayed once. ([#928](https://github.com/element-hq/element-x-android/issues/928))
|
- Make sure Snackbars are only displayed once. ([#928](https://github.com/element-hq/element-x-android/issues/928))
|
||||||
- Fix the orientation of sent images. ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
|
- Fix the orientation of sent images. ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
|
||||||
- Bug reporter crashes when 'send logs' is disabled. ([#1168](https://github.com/element-hq/element-x-android/issues/1168))
|
- Bug reporter crashes when 'send logs' is disabled. ([#1168](https://github.com/element-hq/element-x-android/issues/1168))
|
||||||
- Add missing link to the terms on the analytics setting screen. ([#1177](https://github.com/element-hq/element-x-android/issues/1177))
|
- Add missing link to the terms on the analytics setting screen. ([#1177](https://github.com/element-hq/element-x-android/issues/1177))
|
||||||
- Re-enable `SyncService.withEncryptionSync` to improve decryption of notifications. ([#1198](https://github.com/element-hq/element-x-android/issues/1198))
|
- Re-enable `SyncService.withEncryptionSync` to improve decryption of notifications. ([#1198](https://github.com/element-hq/element-x-android/issues/1198))
|
||||||
- Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/element-hq/element-x-android/issues/1995))
|
- Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/element-hq/element-x-android/issues/1995))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Remove unnecessary year in copyright mention. ([#1187](https://github.com/element-hq/element-x-android/issues/1187))
|
- Remove unnecessary year in copyright mention. ([#1187](https://github.com/element-hq/element-x-android/issues/1187))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.1.5 (2023-08-28)
|
Changes in Element X v0.1.5 (2023-08-28)
|
||||||
|
|
@ -478,7 +539,7 @@ Changes in Element X v0.1.5 (2023-08-28)
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Fix crash when opening any room. ([#1160](https://github.com/element-hq/element-x-android/issues/1160))
|
- Fix crash when opening any room. ([#1160](https://github.com/element-hq/element-x-android/issues/1160))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.1.4 (2023-08-28)
|
Changes in Element X v0.1.4 (2023-08-28)
|
||||||
|
|
@ -486,32 +547,32 @@ Changes in Element X v0.1.4 (2023-08-28)
|
||||||
|
|
||||||
Features ✨
|
Features ✨
|
||||||
----------
|
----------
|
||||||
- Allow cancelling media upload ([#769](https://github.com/element-hq/element-x-android/issues/769))
|
- Allow cancelling media upload ([#769](https://github.com/element-hq/element-x-android/issues/769))
|
||||||
- Enable OIDC support. ([#1127](https://github.com/element-hq/element-x-android/issues/1127))
|
- Enable OIDC support. ([#1127](https://github.com/element-hq/element-x-android/issues/1127))
|
||||||
- Add a "Setting up account" screen, displayed the first time the user logs in to the app (per account). ([#1149](https://github.com/element-hq/element-x-android/issues/1149))
|
- Add a "Setting up account" screen, displayed the first time the user logs in to the app (per account). ([#1149](https://github.com/element-hq/element-x-android/issues/1149))
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Videos sent from the app were cropped in some cases. ([#862](https://github.com/element-hq/element-x-android/issues/862))
|
- Videos sent from the app were cropped in some cases. ([#862](https://github.com/element-hq/element-x-android/issues/862))
|
||||||
- Timeline: sender names are now displayed in one single line. ([#1033](https://github.com/element-hq/element-x-android/issues/1033))
|
- Timeline: sender names are now displayed in one single line. ([#1033](https://github.com/element-hq/element-x-android/issues/1033))
|
||||||
- Fix `TextButtons` being displayed in black. ([#1077](https://github.com/element-hq/element-x-android/issues/1077))
|
- Fix `TextButtons` being displayed in black. ([#1077](https://github.com/element-hq/element-x-android/issues/1077))
|
||||||
- Linkify links in HTML contents. ([#1079](https://github.com/element-hq/element-x-android/issues/1079))
|
- Linkify links in HTML contents. ([#1079](https://github.com/element-hq/element-x-android/issues/1079))
|
||||||
- Fix bug reporter failing after not finding some log files. ([#1082](https://github.com/element-hq/element-x-android/issues/1082))
|
- Fix bug reporter failing after not finding some log files. ([#1082](https://github.com/element-hq/element-x-android/issues/1082))
|
||||||
- Fix rendering of inline elements in list items. ([#1090](https://github.com/element-hq/element-x-android/issues/1090))
|
- Fix rendering of inline elements in list items. ([#1090](https://github.com/element-hq/element-x-android/issues/1090))
|
||||||
- Fix crash RuntimeException "No matching key found for the ciphertext in the stream" ([#1101](https://github.com/element-hq/element-x-android/issues/1101))
|
- Fix crash RuntimeException "No matching key found for the ciphertext in the stream" ([#1101](https://github.com/element-hq/element-x-android/issues/1101))
|
||||||
- Make links in messages clickable again. ([#1111](https://github.com/element-hq/element-x-android/issues/1111))
|
- Make links in messages clickable again. ([#1111](https://github.com/element-hq/element-x-android/issues/1111))
|
||||||
- When event has no id, just cancel parsing the latest room message for a room. ([#1125](https://github.com/element-hq/element-x-android/issues/1125))
|
- When event has no id, just cancel parsing the latest room message for a room. ([#1125](https://github.com/element-hq/element-x-android/issues/1125))
|
||||||
- Only display verification prompt after initial sync is done. ([#1131](https://github.com/element-hq/element-x-android/issues/1131))
|
- Only display verification prompt after initial sync is done. ([#1131](https://github.com/element-hq/element-x-android/issues/1131))
|
||||||
|
|
||||||
In development 🚧
|
In development 🚧
|
||||||
----------------
|
----------------
|
||||||
- [Poll] Add feature flag in developer options ([#1064](https://github.com/element-hq/element-x-android/issues/1064))
|
- [Poll] Add feature flag in developer options ([#1064](https://github.com/element-hq/element-x-android/issues/1064))
|
||||||
- [Polls] Improve UI and render ended state ([#1113](https://github.com/element-hq/element-x-android/issues/1113))
|
- [Polls] Improve UI and render ended state ([#1113](https://github.com/element-hq/element-x-android/issues/1113))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Compound: add `ListItem` and `ListSectionHeader` components. ([#990](https://github.com/element-hq/element-x-android/issues/990))
|
- Compound: add `ListItem` and `ListSectionHeader` components. ([#990](https://github.com/element-hq/element-x-android/issues/990))
|
||||||
- Migrate `object` to `data object` in sealed interface / class #1135 ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
|
- Migrate `object` to `data object` in sealed interface / class #1135 ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.1.2 (2023-08-16)
|
Changes in Element X v0.1.2 (2023-08-16)
|
||||||
|
|
@ -519,20 +580,20 @@ Changes in Element X v0.1.2 (2023-08-16)
|
||||||
|
|
||||||
Bugfixes 🐛
|
Bugfixes 🐛
|
||||||
----------
|
----------
|
||||||
- Filter push notifications using push rules. ([#640](https://github.com/element-hq/element-x-android/issues/640))
|
- Filter push notifications using push rules. ([#640](https://github.com/element-hq/element-x-android/issues/640))
|
||||||
- Use `for` instead of `forEach` in `DefaultDiffCacheInvalidator` to improve performance. ([#1035](https://github.com/element-hq/element-x-android/issues/1035))
|
- Use `for` instead of `forEach` in `DefaultDiffCacheInvalidator` to improve performance. ([#1035](https://github.com/element-hq/element-x-android/issues/1035))
|
||||||
|
|
||||||
In development 🚧
|
In development 🚧
|
||||||
----------------
|
----------------
|
||||||
- [Poll] Render start event in the timeline ([#1031](https://github.com/element-hq/element-x-android/issues/1031))
|
- [Poll] Render start event in the timeline ([#1031](https://github.com/element-hq/element-x-android/issues/1031))
|
||||||
|
|
||||||
Other changes
|
Other changes
|
||||||
-------------
|
-------------
|
||||||
- Add Button component based on Compound designs ([#1021](https://github.com/element-hq/element-x-android/issues/1021))
|
- Add Button component based on Compound designs ([#1021](https://github.com/element-hq/element-x-android/issues/1021))
|
||||||
- Compound: implement dialogs. ([#1043](https://github.com/element-hq/element-x-android/issues/1043))
|
- Compound: implement dialogs. ([#1043](https://github.com/element-hq/element-x-android/issues/1043))
|
||||||
- Compound: customise `IconButton` component. ([#1049](https://github.com/element-hq/element-x-android/issues/1049))
|
- Compound: customise `IconButton` component. ([#1049](https://github.com/element-hq/element-x-android/issues/1049))
|
||||||
- Compound: implement `DropdownMenu` customisations. ([#1050](https://github.com/element-hq/element-x-android/issues/1050))
|
- Compound: implement `DropdownMenu` customisations. ([#1050](https://github.com/element-hq/element-x-android/issues/1050))
|
||||||
- Compound: implement Snackbar component. ([#1054](https://github.com/element-hq/element-x-android/issues/1054))
|
- Compound: implement Snackbar component. ([#1054](https://github.com/element-hq/element-x-android/issues/1054))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element X v0.1.0 (2023-07-19)
|
Changes in Element X v0.1.0 (2023-07-19)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,6 @@ class ElementXApplication : Application(), DaggerComponentOwner {
|
||||||
initializeComponent(TracingInitializer::class.java)
|
initializeComponent(TracingInitializer::class.java)
|
||||||
initializeComponent(CacheCleanerInitializer::class.java)
|
initializeComponent(CacheCleanerInitializer::class.java)
|
||||||
}
|
}
|
||||||
logApplicationInfo()
|
logApplicationInfo(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.bumble.appyx.core.integration.NodeHost
|
import com.bumble.appyx.core.integration.NodeHost
|
||||||
import com.bumble.appyx.core.integrationpoint.NodeActivity
|
import com.bumble.appyx.core.integrationpoint.NodeActivity
|
||||||
import com.bumble.appyx.core.plugin.NodeReadyObserver
|
import com.bumble.appyx.core.plugin.NodeReadyObserver
|
||||||
|
|
@ -39,13 +42,16 @@ import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.theme.Theme
|
import io.element.android.compound.theme.Theme
|
||||||
import io.element.android.compound.theme.isDark
|
import io.element.android.compound.theme.isDark
|
||||||
import io.element.android.compound.theme.mapToTheme
|
import io.element.android.compound.theme.mapToTheme
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenEntryPoint
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenLockState
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenService
|
||||||
import io.element.android.features.lockscreen.api.handleSecureFlag
|
import io.element.android.features.lockscreen.api.handleSecureFlag
|
||||||
import io.element.android.features.lockscreen.api.isLocked
|
|
||||||
import io.element.android.libraries.architecture.bindings
|
import io.element.android.libraries.architecture.bindings
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
|
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
|
||||||
import io.element.android.x.di.AppBindings
|
import io.element.android.x.di.AppBindings
|
||||||
import io.element.android.x.intent.SafeUriHandler
|
import io.element.android.x.intent.SafeUriHandler
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("MainActivity")
|
private val loggerTag = LoggerTag("MainActivity")
|
||||||
|
|
@ -59,27 +65,13 @@ class MainActivity : NodeActivity() {
|
||||||
installSplashScreen()
|
installSplashScreen()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
appBindings = bindings()
|
appBindings = bindings()
|
||||||
appBindings.lockScreenService().handleSecureFlag(this)
|
setupLockManagement(appBindings.lockScreenService(), appBindings.lockScreenEntryPoint())
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
MainContent(appBindings)
|
MainContent(appBindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
override fun onBackPressed() {
|
|
||||||
// If the app is locked, we need to intercept onBackPressed before it goes to OnBackPressedDispatcher.
|
|
||||||
// Indeed, otherwise we would need to trick Appyx backstack management everywhere.
|
|
||||||
// Without this trick, we would get pop operations on the hidden backstack.
|
|
||||||
if (appBindings.lockScreenService().isLocked) {
|
|
||||||
// Do not kill the app in this case, just go to background.
|
|
||||||
moveTaskToBack(false)
|
|
||||||
} else {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainContent(appBindings: AppBindings) {
|
private fun MainContent(appBindings: AppBindings) {
|
||||||
val theme by remember {
|
val theme by remember {
|
||||||
|
|
@ -96,8 +88,8 @@ class MainActivity : NodeActivity() {
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(MaterialTheme.colorScheme.background),
|
.background(MaterialTheme.colorScheme.background),
|
||||||
) {
|
) {
|
||||||
if (migrationState.migrationAction.isSuccess()) {
|
if (migrationState.migrationAction.isSuccess()) {
|
||||||
MainNodeHost()
|
MainNodeHost()
|
||||||
|
|
@ -131,6 +123,22 @@ class MainActivity : NodeActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupLockManagement(
|
||||||
|
lockScreenService: LockScreenService,
|
||||||
|
lockScreenEntryPoint: LockScreenEntryPoint
|
||||||
|
) {
|
||||||
|
lockScreenService.handleSecureFlag(this)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
lockScreenService.lockState.collect { state ->
|
||||||
|
if (state == LockScreenLockState.Locked) {
|
||||||
|
startActivity(lockScreenEntryPoint.pinUnlockIntent(this@MainActivity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when:
|
* Called when:
|
||||||
* - the launcher icon is clicked (if the app is already running);
|
* - the launcher icon is clicked (if the app is already running);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package io.element.android.x.di
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesTo
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
import io.element.android.features.api.MigrationEntryPoint
|
import io.element.android.features.api.MigrationEntryPoint
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenEntryPoint
|
||||||
import io.element.android.features.lockscreen.api.LockScreenService
|
import io.element.android.features.lockscreen.api.LockScreenService
|
||||||
import io.element.android.features.preferences.api.store.AppPreferencesStore
|
import io.element.android.features.preferences.api.store.AppPreferencesStore
|
||||||
import io.element.android.features.rageshake.api.reporter.BugReporter
|
import io.element.android.features.rageshake.api.reporter.BugReporter
|
||||||
|
|
@ -38,4 +39,6 @@ interface AppBindings {
|
||||||
fun preferencesStore(): AppPreferencesStore
|
fun preferencesStore(): AppPreferencesStore
|
||||||
|
|
||||||
fun migrationEntryPoint(): MigrationEntryPoint
|
fun migrationEntryPoint(): MigrationEntryPoint
|
||||||
|
|
||||||
|
fun lockScreenEntryPoint(): LockScreenEntryPoint
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import dagger.Provides
|
||||||
import io.element.android.appconfig.ApplicationConfig
|
import io.element.android.appconfig.ApplicationConfig
|
||||||
import io.element.android.features.messages.impl.timeline.components.customreaction.DefaultEmojibaseProvider
|
import io.element.android.features.messages.impl.timeline.components.customreaction.DefaultEmojibaseProvider
|
||||||
import io.element.android.features.messages.impl.timeline.components.customreaction.EmojibaseProvider
|
import io.element.android.features.messages.impl.timeline.components.customreaction.EmojibaseProvider
|
||||||
|
import io.element.android.libraries.androidutils.system.getVersionCodeFromManifest
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
import io.element.android.libraries.core.meta.BuildType
|
import io.element.android.libraries.core.meta.BuildType
|
||||||
|
|
@ -87,7 +88,7 @@ object AppModule {
|
||||||
// TODO EAx Config.LOW_PRIVACY_LOG_ENABLE,
|
// TODO EAx Config.LOW_PRIVACY_LOG_ENABLE,
|
||||||
lowPrivacyLoggingEnabled = false,
|
lowPrivacyLoggingEnabled = false,
|
||||||
versionName = BuildConfig.VERSION_NAME,
|
versionName = BuildConfig.VERSION_NAME,
|
||||||
versionCode = BuildConfig.VERSION_CODE,
|
versionCode = context.getVersionCodeFromManifest(),
|
||||||
gitRevision = BuildConfig.GIT_REVISION,
|
gitRevision = BuildConfig.GIT_REVISION,
|
||||||
gitBranchName = BuildConfig.GIT_BRANCH_NAME,
|
gitBranchName = BuildConfig.GIT_BRANCH_NAME,
|
||||||
flavorDescription = BuildConfig.FLAVOR_DESCRIPTION,
|
flavorDescription = BuildConfig.FLAVOR_DESCRIPTION,
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,19 @@
|
||||||
|
|
||||||
package io.element.android.x.info
|
package io.element.android.x.info
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import io.element.android.libraries.androidutils.system.getVersionCodeFromManifest
|
||||||
import io.element.android.x.BuildConfig
|
import io.element.android.x.BuildConfig
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
fun logApplicationInfo() {
|
fun logApplicationInfo(context: Context) {
|
||||||
val appVersion = buildString {
|
val appVersion = buildString {
|
||||||
append(BuildConfig.VERSION_NAME)
|
append(BuildConfig.VERSION_NAME)
|
||||||
append(" (")
|
append(" (")
|
||||||
append(BuildConfig.VERSION_CODE)
|
append(context.getVersionCodeFromManifest())
|
||||||
append(") - ")
|
append(") - ")
|
||||||
append(BuildConfig.BUILD_TYPE)
|
append(BuildConfig.BUILD_TYPE)
|
||||||
append(" / ")
|
append(" / ")
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,13 @@
|
||||||
<locale android:name="hu"/>
|
<locale android:name="hu"/>
|
||||||
<locale android:name="in"/>
|
<locale android:name="in"/>
|
||||||
<locale android:name="it"/>
|
<locale android:name="it"/>
|
||||||
|
<locale android:name="ka"/>
|
||||||
|
<locale android:name="pt_BR"/>
|
||||||
<locale android:name="ro"/>
|
<locale android:name="ro"/>
|
||||||
<locale android:name="ru"/>
|
<locale android:name="ru"/>
|
||||||
<locale android:name="sk"/>
|
<locale android:name="sk"/>
|
||||||
<locale android:name="sv"/>
|
<locale android:name="sv"/>
|
||||||
<locale android:name="uk"/>
|
<locale android:name="uk"/>
|
||||||
|
<locale android:name="zh-CN"/>
|
||||||
<locale android:name="zh-TW"/>
|
<locale android:name="zh-TW"/>
|
||||||
</locale-config>
|
</locale-config>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 New Vector Ltd
|
* Copyright (c) 2024 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.notifications.fake
|
package io.element.android.appconfig
|
||||||
|
|
||||||
import io.element.android.libraries.push.impl.notifications.SummaryGroupMessageCreator
|
object MessageComposerConfig {
|
||||||
import io.mockk.mockk
|
/**
|
||||||
|
* Enable the rich text editing in the composer.
|
||||||
class MockkSummaryGroupMessageCreator {
|
*/
|
||||||
val instance = mockk<SummaryGroupMessageCreator>()
|
const val ENABLE_RICH_TEXT_EDITING = true
|
||||||
}
|
}
|
||||||
|
|
@ -20,6 +20,9 @@ object NotificationConfig {
|
||||||
// TODO EAx Implement and set to true at some point
|
// TODO EAx Implement and set to true at some point
|
||||||
const val SUPPORT_MARK_AS_READ_ACTION = false
|
const val SUPPORT_MARK_AS_READ_ACTION = false
|
||||||
|
|
||||||
|
// TODO EAx Implement and set to true at some point
|
||||||
|
const val SUPPORT_JOIN_DECLINE_INVITE = false
|
||||||
|
|
||||||
// TODO EAx Implement and set to true at some point
|
// TODO EAx Implement and set to true at some point
|
||||||
const val SUPPORT_QUICK_REPLY_ACTION = false
|
const val SUPPORT_QUICK_REPLY_ACTION = false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
|
||||||
import com.bumble.appyx.navmodel.backstack.operation.replace
|
import com.bumble.appyx.navmodel.backstack.operation.replace
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.appnav.loggedin.LoggedInNode
|
import io.element.android.appnav.loggedin.LoggedInNode
|
||||||
import io.element.android.appnav.room.RoomFlowNode
|
import io.element.android.appnav.room.RoomFlowNode
|
||||||
|
|
@ -46,9 +47,6 @@ import io.element.android.features.createroom.api.CreateRoomEntryPoint
|
||||||
import io.element.android.features.ftue.api.FtueEntryPoint
|
import io.element.android.features.ftue.api.FtueEntryPoint
|
||||||
import io.element.android.features.ftue.api.state.FtueService
|
import io.element.android.features.ftue.api.state.FtueService
|
||||||
import io.element.android.features.ftue.api.state.FtueState
|
import io.element.android.features.ftue.api.state.FtueState
|
||||||
import io.element.android.features.lockscreen.api.LockScreenEntryPoint
|
|
||||||
import io.element.android.features.lockscreen.api.LockScreenLockState
|
|
||||||
import io.element.android.features.lockscreen.api.LockScreenService
|
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||||
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
||||||
|
|
@ -99,8 +97,6 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
private val networkMonitor: NetworkMonitor,
|
private val networkMonitor: NetworkMonitor,
|
||||||
private val ftueService: FtueService,
|
private val ftueService: FtueService,
|
||||||
private val lockScreenEntryPoint: LockScreenEntryPoint,
|
|
||||||
private val lockScreenStateService: LockScreenService,
|
|
||||||
private val roomDirectoryEntryPoint: RoomDirectoryEntryPoint,
|
private val roomDirectoryEntryPoint: RoomDirectoryEntryPoint,
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
snackbarDispatcher: SnackbarDispatcher,
|
snackbarDispatcher: SnackbarDispatcher,
|
||||||
|
|
@ -110,7 +106,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
savedStateMap = buildContext.savedStateMap,
|
savedStateMap = buildContext.savedStateMap,
|
||||||
),
|
),
|
||||||
permanentNavModel = PermanentNavModel(
|
permanentNavModel = PermanentNavModel(
|
||||||
navTargets = setOf(NavTarget.LoggedInPermanent, NavTarget.LockPermanent),
|
navTargets = setOf(NavTarget.LoggedInPermanent),
|
||||||
savedStateMap = buildContext.savedStateMap,
|
savedStateMap = buildContext.savedStateMap,
|
||||||
),
|
),
|
||||||
buildContext = buildContext,
|
buildContext = buildContext,
|
||||||
|
|
@ -188,15 +184,14 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object LoggedInPermanent : NavTarget
|
data object LoggedInPermanent : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data object LockPermanent : NavTarget
|
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object RoomList : NavTarget
|
data object RoomList : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Room(
|
data class Room(
|
||||||
val roomIdOrAlias: RoomIdOrAlias,
|
val roomIdOrAlias: RoomIdOrAlias,
|
||||||
|
val serverNames: List<String> = emptyList(),
|
||||||
|
val trigger: JoinedRoom.Trigger? = null,
|
||||||
val roomDescription: RoomDescription? = null,
|
val roomDescription: RoomDescription? = null,
|
||||||
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages()
|
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages()
|
||||||
) : NavTarget
|
) : NavTarget
|
||||||
|
|
@ -232,38 +227,33 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
NavTarget.LoggedInPermanent -> {
|
NavTarget.LoggedInPermanent -> {
|
||||||
createNode<LoggedInNode>(buildContext)
|
createNode<LoggedInNode>(buildContext)
|
||||||
}
|
}
|
||||||
NavTarget.LockPermanent -> {
|
|
||||||
lockScreenEntryPoint.nodeBuilder(this, buildContext)
|
|
||||||
.target(LockScreenEntryPoint.Target.Unlock)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
NavTarget.RoomList -> {
|
NavTarget.RoomList -> {
|
||||||
val callback = object : RoomListEntryPoint.Callback {
|
val callback = object : RoomListEntryPoint.Callback {
|
||||||
override fun onRoomClicked(roomId: RoomId) {
|
override fun onRoomClick(roomId: RoomId) {
|
||||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
|
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSettingsClicked() {
|
override fun onSettingsClick() {
|
||||||
backstack.push(NavTarget.Settings())
|
backstack.push(NavTarget.Settings())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateRoomClicked() {
|
override fun onCreateRoomClick() {
|
||||||
backstack.push(NavTarget.CreateRoom)
|
backstack.push(NavTarget.CreateRoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionConfirmRecoveryKeyClicked() {
|
override fun onSessionConfirmRecoveryKeyClick() {
|
||||||
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey))
|
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRoomSettingsClicked(roomId: RoomId) {
|
override fun onRoomSettingsClick(roomId: RoomId) {
|
||||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.Details))
|
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.Details))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReportBugClicked() {
|
override fun onReportBugClick() {
|
||||||
plugins<Callback>().forEach { it.onOpenBugReport() }
|
plugins<Callback>().forEach { it.onOpenBugReport() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRoomDirectorySearchClicked() {
|
override fun onRoomDirectorySearchClick() {
|
||||||
backstack.push(NavTarget.RoomDirectorySearch)
|
backstack.push(NavTarget.RoomDirectorySearch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +272,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias()) }
|
coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPermalinkClicked(data: PermalinkData) {
|
override fun onPermalinkClick(data: PermalinkData) {
|
||||||
when (data) {
|
when (data) {
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
// Should not happen (handled by MessagesNode)
|
// Should not happen (handled by MessagesNode)
|
||||||
|
|
@ -292,8 +282,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
backstack.push(
|
backstack.push(
|
||||||
NavTarget.Room(
|
NavTarget.Room(
|
||||||
roomIdOrAlias = data.roomIdOrAlias,
|
roomIdOrAlias = data.roomIdOrAlias,
|
||||||
|
serverNames = data.viaParameters,
|
||||||
|
trigger = JoinedRoom.Trigger.Timeline,
|
||||||
initialElement = RoomNavigationTarget.Messages(data.eventId),
|
initialElement = RoomNavigationTarget.Messages(data.eventId),
|
||||||
// TODO Use the viaParameters
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -311,6 +302,8 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
val inputs = RoomFlowNode.Inputs(
|
val inputs = RoomFlowNode.Inputs(
|
||||||
roomIdOrAlias = navTarget.roomIdOrAlias,
|
roomIdOrAlias = navTarget.roomIdOrAlias,
|
||||||
roomDescription = Optional.ofNullable(navTarget.roomDescription),
|
roomDescription = Optional.ofNullable(navTarget.roomDescription),
|
||||||
|
serverNames = navTarget.serverNames,
|
||||||
|
trigger = Optional.ofNullable(navTarget.trigger),
|
||||||
initialElement = navTarget.initialElement
|
initialElement = navTarget.initialElement
|
||||||
)
|
)
|
||||||
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, callback))
|
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, callback))
|
||||||
|
|
@ -332,7 +325,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
plugins<Callback>().forEach { it.onOpenBugReport() }
|
plugins<Callback>().forEach { it.onOpenBugReport() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSecureBackupClicked() {
|
override fun onSecureBackupClick() {
|
||||||
backstack.push(NavTarget.SecureBackup())
|
backstack.push(NavTarget.SecureBackup())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,12 +363,14 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
NavTarget.RoomDirectorySearch -> {
|
NavTarget.RoomDirectorySearch -> {
|
||||||
roomDirectoryEntryPoint.nodeBuilder(this, buildContext)
|
roomDirectoryEntryPoint.nodeBuilder(this, buildContext)
|
||||||
.callback(object : RoomDirectoryEntryPoint.Callback {
|
.callback(object : RoomDirectoryEntryPoint.Callback {
|
||||||
override fun onRoomJoined(roomId: RoomId) {
|
override fun onResultClick(roomDescription: RoomDescription) {
|
||||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
|
backstack.push(
|
||||||
}
|
NavTarget.Room(
|
||||||
|
roomIdOrAlias = roomDescription.roomId.toRoomIdOrAlias(),
|
||||||
override fun onResultClicked(roomDescription: RoomDescription) {
|
roomDescription = roomDescription,
|
||||||
backstack.push(NavTarget.Room(roomDescription.roomId.toRoomIdOrAlias(), roomDescription))
|
trigger = JoinedRoom.Trigger.RoomDirectory,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -383,7 +378,12 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun attachRoom(roomIdOrAlias: RoomIdOrAlias, eventId: EventId? = null) {
|
suspend fun attachRoom(
|
||||||
|
roomIdOrAlias: RoomIdOrAlias,
|
||||||
|
serverNames: List<String> = emptyList(),
|
||||||
|
trigger: JoinedRoom.Trigger? = null,
|
||||||
|
eventId: EventId? = null,
|
||||||
|
) {
|
||||||
waitForNavTargetAttached { navTarget ->
|
waitForNavTargetAttached { navTarget ->
|
||||||
navTarget is NavTarget.RoomList
|
navTarget is NavTarget.RoomList
|
||||||
}
|
}
|
||||||
|
|
@ -391,6 +391,8 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
backstack.push(
|
backstack.push(
|
||||||
NavTarget.Room(
|
NavTarget.Room(
|
||||||
roomIdOrAlias = roomIdOrAlias,
|
roomIdOrAlias = roomIdOrAlias,
|
||||||
|
serverNames = serverNames,
|
||||||
|
trigger = trigger,
|
||||||
initialElement = RoomNavigationTarget.Messages(
|
initialElement = RoomNavigationTarget.Messages(
|
||||||
focusedEventId = eventId
|
focusedEventId = eventId
|
||||||
)
|
)
|
||||||
|
|
@ -415,15 +417,11 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
val lockScreenState by lockScreenStateService.lockState.collectAsState()
|
|
||||||
val ftueState by ftueService.state.collectAsState()
|
val ftueState by ftueService.state.collectAsState()
|
||||||
BackstackView()
|
BackstackView()
|
||||||
if (ftueState is FtueState.Complete) {
|
if (ftueState is FtueState.Complete) {
|
||||||
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent)
|
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent)
|
||||||
}
|
}
|
||||||
if (lockScreenState == LockScreenLockState.Locked) {
|
|
||||||
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LockPermanent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import com.bumble.appyx.navmodel.backstack.operation.pop
|
||||||
import com.bumble.appyx.navmodel.backstack.operation.push
|
import com.bumble.appyx.navmodel.backstack.operation.push
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.appnav.di.MatrixClientsHolder
|
import io.element.android.appnav.di.MatrixClientsHolder
|
||||||
import io.element.android.appnav.intent.IntentResolver
|
import io.element.android.appnav.intent.IntentResolver
|
||||||
|
|
@ -295,6 +296,8 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
is PermalinkData.RoomLink -> {
|
is PermalinkData.RoomLink -> {
|
||||||
attachRoom(
|
attachRoom(
|
||||||
roomIdOrAlias = permalinkData.roomIdOrAlias,
|
roomIdOrAlias = permalinkData.roomIdOrAlias,
|
||||||
|
trigger = JoinedRoom.Trigger.MobilePermalink,
|
||||||
|
serverNames = permalinkData.viaParameters,
|
||||||
eventId = permalinkData.eventId,
|
eventId = permalinkData.eventId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatu
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LoggedInPresenter @Inject constructor(
|
class LoggedInPresenter @Inject constructor(
|
||||||
|
|
@ -55,10 +56,26 @@ class LoggedInPresenter @Inject constructor(
|
||||||
LaunchedEffect(isVerified) {
|
LaunchedEffect(isVerified) {
|
||||||
if (isVerified) {
|
if (isVerified) {
|
||||||
// Ensure pusher is registered
|
// Ensure pusher is registered
|
||||||
// TODO Manually select push provider for now
|
val currentPushProvider = pushService.getCurrentPushProvider()
|
||||||
val pushProvider = pushService.getAvailablePushProviders().firstOrNull() ?: return@LaunchedEffect
|
val result = if (currentPushProvider == null) {
|
||||||
val distributor = pushProvider.getDistributors().firstOrNull() ?: return@LaunchedEffect
|
// Register with the first available push provider
|
||||||
pushService.registerWith(matrixClient, pushProvider, distributor)
|
val pushProvider = pushService.getAvailablePushProviders().firstOrNull() ?: return@LaunchedEffect
|
||||||
|
val distributor = pushProvider.getDistributors().firstOrNull() ?: return@LaunchedEffect
|
||||||
|
pushService.registerWith(matrixClient, pushProvider, distributor)
|
||||||
|
} else {
|
||||||
|
val currentPushDistributor = currentPushProvider.getCurrentDistributor(matrixClient)
|
||||||
|
if (currentPushDistributor == null) {
|
||||||
|
// Register with the first available distributor
|
||||||
|
val distributor = currentPushProvider.getDistributors().firstOrNull() ?: return@LaunchedEffect
|
||||||
|
pushService.registerWith(matrixClient, currentPushProvider, distributor)
|
||||||
|
} else {
|
||||||
|
// Re-register with the current distributor
|
||||||
|
pushService.registerWith(matrixClient, currentPushProvider, currentPushDistributor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.onFailure {
|
||||||
|
Timber.e(it, "Failed to register pusher")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
import com.bumble.appyx.navmodel.backstack.operation.newRoot
|
import com.bumble.appyx.navmodel.backstack.operation.newRoot
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.appnav.room.joined.JoinedRoomFlowNode
|
import io.element.android.appnav.room.joined.JoinedRoomFlowNode
|
||||||
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
|
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
|
||||||
|
|
@ -54,6 +55,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||||
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
@ -83,6 +85,8 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
data class Inputs(
|
data class Inputs(
|
||||||
val roomIdOrAlias: RoomIdOrAlias,
|
val roomIdOrAlias: RoomIdOrAlias,
|
||||||
val roomDescription: Optional<RoomDescription>,
|
val roomDescription: Optional<RoomDescription>,
|
||||||
|
val serverNames: List<String>,
|
||||||
|
val trigger: Optional<JoinedRoom.Trigger>,
|
||||||
val initialElement: RoomNavigationTarget,
|
val initialElement: RoomNavigationTarget,
|
||||||
) : NodeInputs
|
) : NodeInputs
|
||||||
|
|
||||||
|
|
@ -96,7 +100,11 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
data class Resolving(val roomAlias: RoomAlias) : NavTarget
|
data class Resolving(val roomAlias: RoomAlias) : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class JoinRoom(val roomId: RoomId) : NavTarget
|
data class JoinRoom(
|
||||||
|
val roomId: RoomId,
|
||||||
|
val serverNames: List<String>,
|
||||||
|
val trigger: im.vector.app.features.analytics.plan.JoinedRoom.Trigger,
|
||||||
|
) : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class JoinedRoom(val roomId: RoomId) : NavTarget
|
data class JoinedRoom(val roomId: RoomId) : NavTarget
|
||||||
|
|
@ -114,13 +122,13 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
backstack.newRoot(NavTarget.Resolving(i.roomAlias))
|
backstack.newRoot(NavTarget.Resolving(i.roomAlias))
|
||||||
}
|
}
|
||||||
is RoomIdOrAlias.Id -> {
|
is RoomIdOrAlias.Id -> {
|
||||||
subscribeToRoomInfoFlow(i.roomId)
|
subscribeToRoomInfoFlow(i.roomId, inputs.serverNames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeToRoomInfoFlow(roomId: RoomId) {
|
private fun subscribeToRoomInfoFlow(roomId: RoomId, serverNames: List<String>) {
|
||||||
val roomInfoFlow = client.getRoomInfoFlow(
|
val roomInfoFlow = client.getRoomInfoFlow(
|
||||||
roomId = roomId
|
roomId = roomId
|
||||||
).map { it.getOrNull() }
|
).map { it.getOrNull() }
|
||||||
|
|
@ -136,7 +144,13 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
// we can have a space here in case the space has just been joined.
|
// we can have a space here in case the space has just been joined.
|
||||||
// So navigate to the JoinRoom target for now, which will
|
// So navigate to the JoinRoom target for now, which will
|
||||||
// handle the space not supported screen
|
// handle the space not supported screen
|
||||||
backstack.newRoot(NavTarget.JoinRoom(roomId))
|
backstack.newRoot(
|
||||||
|
NavTarget.JoinRoom(
|
||||||
|
roomId = roomId,
|
||||||
|
serverNames = serverNames,
|
||||||
|
trigger = inputs.trigger.getOrNull() ?: JoinedRoom.Trigger.Invite,
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +161,13 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// Was invited or the room is not known, display the join room screen
|
// Was invited or the room is not known, display the join room screen
|
||||||
backstack.newRoot(NavTarget.JoinRoom(roomId))
|
backstack.newRoot(
|
||||||
|
NavTarget.JoinRoom(
|
||||||
|
roomId = roomId,
|
||||||
|
serverNames = serverNames,
|
||||||
|
trigger = inputs.trigger.getOrNull() ?: JoinedRoom.Trigger.Invite,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(lifecycleScope)
|
}.launchIn(lifecycleScope)
|
||||||
|
|
@ -158,8 +178,11 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
is NavTarget.Loading -> loadingNode(buildContext)
|
is NavTarget.Loading -> loadingNode(buildContext)
|
||||||
is NavTarget.Resolving -> {
|
is NavTarget.Resolving -> {
|
||||||
val callback = object : RoomAliasResolverEntryPoint.Callback {
|
val callback = object : RoomAliasResolverEntryPoint.Callback {
|
||||||
override fun onAliasResolved(roomId: RoomId) {
|
override fun onAliasResolved(data: ResolvedRoomAlias) {
|
||||||
subscribeToRoomInfoFlow(roomId)
|
subscribeToRoomInfoFlow(
|
||||||
|
roomId = data.roomId,
|
||||||
|
serverNames = data.servers,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val params = RoomAliasResolverEntryPoint.Params(navTarget.roomAlias)
|
val params = RoomAliasResolverEntryPoint.Params(navTarget.roomAlias)
|
||||||
|
|
@ -173,6 +196,8 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
roomId = navTarget.roomId,
|
roomId = navTarget.roomId,
|
||||||
roomIdOrAlias = inputs.roomIdOrAlias,
|
roomIdOrAlias = inputs.roomIdOrAlias,
|
||||||
roomDescription = inputs.roomDescription,
|
roomDescription = inputs.roomDescription,
|
||||||
|
serverNames = navTarget.serverNames,
|
||||||
|
trigger = navTarget.trigger,
|
||||||
)
|
)
|
||||||
joinRoomEntryPoint.createNode(this, buildContext, inputs)
|
joinRoomEntryPoint.createNode(this, buildContext, inputs)
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +217,7 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
LoadingRoomNodeView(
|
LoadingRoomNodeView(
|
||||||
state = LoadingRoomState.Loading,
|
state = LoadingRoomState.Loading,
|
||||||
hasNetworkConnection = networkStatus == NetworkStatus.Online,
|
hasNetworkConnection = networkStatus == NetworkStatus.Online,
|
||||||
onBackClicked = { navigateUp() },
|
onBackClick = { navigateUp() },
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,14 +121,14 @@ class JoinedRoomFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadingNode(buildContext: BuildContext, onBackClicked: () -> Unit) = node(buildContext) { modifier ->
|
private fun loadingNode(buildContext: BuildContext, onBackClick: () -> Unit) = node(buildContext) { modifier ->
|
||||||
val loadingRoomState by loadingRoomStateStateFlow.collectAsState()
|
val loadingRoomState by loadingRoomStateStateFlow.collectAsState()
|
||||||
val networkStatus by networkMonitor.connectivity.collectAsState()
|
val networkStatus by networkMonitor.connectivity.collectAsState()
|
||||||
LoadingRoomNodeView(
|
LoadingRoomNodeView(
|
||||||
state = loadingRoomState,
|
state = loadingRoomState,
|
||||||
hasNetworkConnection = networkStatus == NetworkStatus.Online,
|
hasNetworkConnection = networkStatus == NetworkStatus.Online,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackClicked = onBackClicked
|
onBackClick = onBackClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ class JoinedRoomLoadedFlowNode @AssistedInject constructor(
|
||||||
), DaggerComponentOwner {
|
), DaggerComponentOwner {
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onOpenRoom(roomId: RoomId)
|
fun onOpenRoom(roomId: RoomId)
|
||||||
fun onPermalinkClicked(data: PermalinkData)
|
fun onPermalinkClick(data: PermalinkData)
|
||||||
fun onForwardedToSingleRoom(roomId: RoomId)
|
fun onForwardedToSingleRoom(roomId: RoomId)
|
||||||
fun onOpenGlobalNotificationSettings()
|
fun onOpenGlobalNotificationSettings()
|
||||||
}
|
}
|
||||||
|
|
@ -144,16 +144,16 @@ class JoinedRoomLoadedFlowNode @AssistedInject constructor(
|
||||||
return when (navTarget) {
|
return when (navTarget) {
|
||||||
is NavTarget.Messages -> {
|
is NavTarget.Messages -> {
|
||||||
val callback = object : MessagesEntryPoint.Callback {
|
val callback = object : MessagesEntryPoint.Callback {
|
||||||
override fun onRoomDetailsClicked() {
|
override fun onRoomDetailsClick() {
|
||||||
backstack.push(NavTarget.RoomDetails)
|
backstack.push(NavTarget.RoomDetails)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUserDataClicked(userId: UserId) {
|
override fun onUserDataClick(userId: UserId) {
|
||||||
backstack.push(NavTarget.RoomMemberDetails(userId))
|
backstack.push(NavTarget.RoomMemberDetails(userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPermalinkClicked(data: PermalinkData) {
|
override fun onPermalinkClick(data: PermalinkData) {
|
||||||
callbacks.forEach { it.onPermalinkClicked(data) }
|
callbacks.forEach { it.onPermalinkClick(data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onForwardedToSingleRoom(roomId: RoomId) {
|
override fun onForwardedToSingleRoom(roomId: RoomId) {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
fun LoadingRoomNodeView(
|
fun LoadingRoomNodeView(
|
||||||
state: LoadingRoomState,
|
state: LoadingRoomState,
|
||||||
hasNetworkConnection: Boolean,
|
hasNetworkConnection: Boolean,
|
||||||
onBackClicked: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -54,7 +54,7 @@ fun LoadingRoomNodeView(
|
||||||
topBar = {
|
topBar = {
|
||||||
Column {
|
Column {
|
||||||
ConnectivityIndicatorView(isOnline = hasNetworkConnection)
|
ConnectivityIndicatorView(isOnline = hasNetworkConnection)
|
||||||
LoadingRoomTopBar(onBackClicked)
|
LoadingRoomTopBar(onBackClick)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content = { padding ->
|
content = { padding ->
|
||||||
|
|
@ -83,11 +83,11 @@ fun LoadingRoomNodeView(
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun LoadingRoomTopBar(
|
private fun LoadingRoomTopBar(
|
||||||
onBackClicked: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
BackButton(onClick = onBackClicked)
|
BackButton(onClick = onBackClick)
|
||||||
},
|
},
|
||||||
title = {
|
title = {
|
||||||
IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp)
|
IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp)
|
||||||
|
|
@ -101,7 +101,7 @@ private fun LoadingRoomTopBar(
|
||||||
internal fun LoadingRoomNodeViewPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) = ElementPreview {
|
internal fun LoadingRoomNodeViewPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) = ElementPreview {
|
||||||
LoadingRoomNodeView(
|
LoadingRoomNodeView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackClicked = {},
|
onBackClick = {},
|
||||||
hasNetworkConnection = false
|
hasNetworkConnection = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ class JoinRoomLoadedFlowNodeTest {
|
||||||
)
|
)
|
||||||
val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper()
|
val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper()
|
||||||
// WHEN
|
// WHEN
|
||||||
fakeMessagesEntryPoint.callback?.onRoomDetailsClicked()
|
fakeMessagesEntryPoint.callback?.onRoomDetailsClick()
|
||||||
// THEN
|
// THEN
|
||||||
roomFlowNodeTestHelper.assertChildHasLifecycle(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED)
|
roomFlowNodeTestHelper.assertChildHasLifecycle(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED)
|
||||||
val roomDetailsNode = roomFlowNode.childNode(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails)!!
|
val roomDetailsNode = roomFlowNode.childNode(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails)!!
|
||||||
|
|
|
||||||
|
|
@ -20,21 +20,21 @@ import com.bumble.appyx.core.state.MutableSavedStateMapImpl
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService
|
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class MatrixClientsHolderTest {
|
class MatrixClientsHolderTest {
|
||||||
@Test
|
@Test
|
||||||
fun `test getOrNull`() {
|
fun `test getOrNull`() {
|
||||||
val fakeAuthenticationService = FakeAuthenticationService()
|
val fakeAuthenticationService = FakeMatrixAuthenticationService()
|
||||||
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
||||||
assertThat(matrixClientsHolder.getOrNull(A_SESSION_ID)).isNull()
|
assertThat(matrixClientsHolder.getOrNull(A_SESSION_ID)).isNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test getOrRestore`() = runTest {
|
fun `test getOrRestore`() = runTest {
|
||||||
val fakeAuthenticationService = FakeAuthenticationService()
|
val fakeAuthenticationService = FakeMatrixAuthenticationService()
|
||||||
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
||||||
val fakeMatrixClient = FakeMatrixClient()
|
val fakeMatrixClient = FakeMatrixClient()
|
||||||
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
||||||
|
|
@ -47,7 +47,7 @@ class MatrixClientsHolderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test remove`() = runTest {
|
fun `test remove`() = runTest {
|
||||||
val fakeAuthenticationService = FakeAuthenticationService()
|
val fakeAuthenticationService = FakeMatrixAuthenticationService()
|
||||||
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
||||||
val fakeMatrixClient = FakeMatrixClient()
|
val fakeMatrixClient = FakeMatrixClient()
|
||||||
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
||||||
|
|
@ -60,7 +60,7 @@ class MatrixClientsHolderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test remove all`() = runTest {
|
fun `test remove all`() = runTest {
|
||||||
val fakeAuthenticationService = FakeAuthenticationService()
|
val fakeAuthenticationService = FakeMatrixAuthenticationService()
|
||||||
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
||||||
val fakeMatrixClient = FakeMatrixClient()
|
val fakeMatrixClient = FakeMatrixClient()
|
||||||
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
||||||
|
|
@ -73,7 +73,7 @@ class MatrixClientsHolderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test save and restore`() = runTest {
|
fun `test save and restore`() = runTest {
|
||||||
val fakeAuthenticationService = FakeAuthenticationService()
|
val fakeAuthenticationService = FakeMatrixAuthenticationService()
|
||||||
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
val matrixClientsHolder = MatrixClientsHolder(fakeAuthenticationService)
|
||||||
val fakeMatrixClient = FakeMatrixClient()
|
val fakeMatrixClient = FakeMatrixClient()
|
||||||
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
fakeAuthenticationService.givenMatrixClient(fakeMatrixClient)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.A_THREAD_ID
|
import io.element.android.libraries.matrix.test.A_THREAD_ID
|
||||||
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
|
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
import org.junit.Assert.assertThrows
|
import org.junit.Assert.assertThrows
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
@ -229,7 +230,7 @@ class IntentResolverTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createIntentResolver(
|
private fun createIntentResolver(
|
||||||
permalinkParserResult: () -> PermalinkData = { throw NotImplementedError() }
|
permalinkParserResult: () -> PermalinkData = { lambdaError() }
|
||||||
): IntentResolver {
|
): IntentResolver {
|
||||||
return IntentResolver(
|
return IntentResolver(
|
||||||
deeplinkParser = DeeplinkParser(),
|
deeplinkParser = DeeplinkParser(),
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ allprojects {
|
||||||
config.from(files("$rootDir/tools/detekt/detekt.yml"))
|
config.from(files("$rootDir/tools/detekt/detekt.yml"))
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
detektPlugins("io.nlopez.compose.rules:detekt:0.3.12")
|
detektPlugins("io.nlopez.compose.rules:detekt:0.4.3")
|
||||||
}
|
}
|
||||||
|
|
||||||
// KtLint
|
// KtLint
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix session verification being asked again for already verified users.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
RoomMember screen: fallback to userProfile data, if the member is not a user of the room.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Instead of displaying 'create new recovery key' on the session verification screen when there is no other session active, display it always under the 'enter recovery key' screen.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Migrate application data.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add support for expected decryption errors due to membership (UX and analytics).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Let the SDK manage the file log cleanup, and keep one week of log.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Handle permalink navigation to Events.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Adjust the typography used in the selected user component so a user's display name fits better.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
User display name overflows in timeline messages when it's way too long.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Pretty-print event JSON in debug viewer
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add support for external permalinks.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Ensure the application open the room when a notification is clicked.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Enable support for Android per-app language preferences
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
UX cleanup: reorder options in the main settings screen.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Analytics: Add support to report current session verification and recovery state
|
|
||||||
1
changelog.d/2809.bugfix
Normal file
1
changelog.d/2809.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Render selected/deselected room list filters on top
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Enforce mandatory session verification only for new logins.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
UX cleanup: room details screen, add new CTA buttons for Invite and Call actions.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
UX cleanup: user profile. Move send DM to a call to action button, add 'Call' CTA too.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add room badges to room details screen.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Make log less verbose, make sure we upload as many log files as possible before reaching the request size limit of the bug reporting service, discard older logs if they don't fit.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Remove 'Join' button in room directory search results.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add missing `app_id` and `Version` properties to bug reports.
|
|
||||||
1
changelog.d/2893.misc
Normal file
1
changelog.d/2893.misc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
BugReporting | Add public device keys to rageshakes
|
||||||
1
changelog.d/2896.bugfix
Normal file
1
changelog.d/2896.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Set auto captilization, multiline and autocompletion flags for the markdown EditText.
|
||||||
1
changelog.d/2898.bugfix
Normal file
1
changelog.d/2898.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Restoree Markdown text input contents when returning to the room screen.
|
||||||
1
changelog.d/2912.misc
Normal file
1
changelog.d/2912.misc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Move push provider setting to the "Notifications" screen and display it only when several push provider are available.
|
||||||
1
changelog.d/2917.bugfix
Normal file
1
changelog.d/2917.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed sending rich content from android keyboards on the markdown text input
|
||||||
3
changelog.d/2924.misc
Normal file
3
changelog.d/2924.misc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Simplify notifications by removing the custom persistence layer.
|
||||||
|
|
||||||
|
Bump minSdk to 24 (Android 7).
|
||||||
1
changelog.d/2930.misc
Normal file
1
changelog.d/2930.misc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add a feature flag ShowBlockedUsersDetails, disabled by default to render display name and avatar of blocked users in the blocked users list.
|
||||||
10
fastlane/metadata/android/en-US/changelogs/40004120.txt
Normal file
10
fastlane/metadata/android/en-US/changelogs/40004120.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
Main changes in this version:
|
||||||
|
|
||||||
|
- Added support for opening matrix URLs inside the app and navigating to replied to messages.
|
||||||
|
- Added per-app language support for Android 13+.
|
||||||
|
- Session verification is no longer mandatory for already logged in users.
|
||||||
|
- Better log handling.
|
||||||
|
- Fixed CVE-2024-34353 / GHSA-9ggc-845v-gcgv.
|
||||||
|
- UX improvements.
|
||||||
|
|
||||||
|
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||||
2
fastlane/metadata/android/en-US/changelogs/40004130.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40004130.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Main changes in this version: Add plain text editor based on Markdown input.
|
||||||
|
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_settings_help_us_improve">"გააზიარეთ ანონიმური გამოყენების მონაცემები, რათა დაგვეხმაროთ პრობლემების იდენტიფიცირებაში."</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms">"შეგიძლიათ, წაიკითხოთ ჩვენი ყველა პირობა %1$s."</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms_content_link">"აქ"</string>
|
||||||
|
<string name="screen_analytics_settings_share_data">"გააზიარეთ ანალიტიკური მონაცემები"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_settings_help_us_improve">"Partilhe dados de utilização anónimos para nos ajudar a identificar problemas."</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms">"Podes ler todos os nossos termos %1$s."</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms_content_link">"aqui"</string>
|
||||||
|
<string name="screen_analytics_settings_share_data">"Partilhar dados de utilização"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_settings_help_us_improve">"共享匿名使用数据以帮助我们排查问题。"</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms">"您可以阅读我们的所有条款 %1$s。"</string>
|
||||||
|
<string name="screen_analytics_settings_read_terms_content_link">"此处"</string>
|
||||||
|
<string name="screen_analytics_settings_share_data">"共享分析数据"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -63,15 +63,15 @@ fun AnalyticsOptInView(
|
||||||
) {
|
) {
|
||||||
val eventSink = state.eventSink
|
val eventSink = state.eventSink
|
||||||
|
|
||||||
fun onTermsAccepted() {
|
fun onAcceptTerms() {
|
||||||
eventSink(AnalyticsOptInEvents.EnableAnalytics(true))
|
eventSink(AnalyticsOptInEvents.EnableAnalytics(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTermsDeclined() {
|
fun onDeclineTerms() {
|
||||||
eventSink(AnalyticsOptInEvents.EnableAnalytics(false))
|
eventSink(AnalyticsOptInEvents.EnableAnalytics(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
BackHandler(onBack = ::onTermsDeclined)
|
BackHandler(onBack = ::onDeclineTerms)
|
||||||
HeaderFooterPage(
|
HeaderFooterPage(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
@ -82,8 +82,8 @@ fun AnalyticsOptInView(
|
||||||
content = { AnalyticsOptInContent() },
|
content = { AnalyticsOptInContent() },
|
||||||
footer = {
|
footer = {
|
||||||
AnalyticsOptInFooter(
|
AnalyticsOptInFooter(
|
||||||
onTermsAccepted = ::onTermsAccepted,
|
onAcceptTerms = ::onAcceptTerms,
|
||||||
onTermsDeclined = ::onTermsDeclined,
|
onDeclineTerms = ::onDeclineTerms,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -165,19 +165,19 @@ private fun AnalyticsOptInContent() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AnalyticsOptInFooter(
|
private fun AnalyticsOptInFooter(
|
||||||
onTermsAccepted: () -> Unit,
|
onAcceptTerms: () -> Unit,
|
||||||
onTermsDeclined: () -> Unit,
|
onDeclineTerms: () -> Unit,
|
||||||
) {
|
) {
|
||||||
ButtonColumnMolecule {
|
ButtonColumnMolecule {
|
||||||
Button(
|
Button(
|
||||||
text = stringResource(id = CommonStrings.action_ok),
|
text = stringResource(id = CommonStrings.action_ok),
|
||||||
onClick = onTermsAccepted,
|
onClick = onAcceptTerms,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
TextButton(
|
TextButton(
|
||||||
text = stringResource(id = CommonStrings.action_not_now),
|
text = stringResource(id = CommonStrings.action_not_now),
|
||||||
size = ButtonSize.Medium,
|
size = ButtonSize.Medium,
|
||||||
onClick = onTermsDeclined,
|
onClick = onDeclineTerms,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_prompt_data_usage">"ჩვენ არ ჩავწერთ და არ დავაფიქსირებთ პერსონალურ მონაცემებს"</string>
|
||||||
|
<string name="screen_analytics_prompt_help_us_improve">"გააზიარეთ ანონიმური გამოყენების მონაცემები, რათა დაგვეხმაროთ პრობლემების იდენტიფიცირებაში."</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms">"შეგიძლიათ, წაიკითხოთ ჩვენი ყველა პირობა %1$s."</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms_content_link">"აქ"</string>
|
||||||
|
<string name="screen_analytics_prompt_settings">"ამის გამორთვა ნებისმიერ დროს შეგიძლიათ"</string>
|
||||||
|
<string name="screen_analytics_prompt_third_party_sharing">"თქვენს მონაცემებს მესამე პირს არ გადავცემთ"</string>
|
||||||
|
<string name="screen_analytics_prompt_title">"დაგვეხმარეთ, გავაუმჯობესოთ %1$s"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_prompt_data_usage">"Não recolheremos ou analisaremos quaisquer dados pessoais"</string>
|
||||||
|
<string name="screen_analytics_prompt_help_us_improve">"Partilhe dados de utilização anónimos para nos ajudar a identificar problemas."</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms">"Podes ler todos os nossos termos %1$s."</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms_content_link">"aqui"</string>
|
||||||
|
<string name="screen_analytics_prompt_settings">"Podes desligar qualquer momento"</string>
|
||||||
|
<string name="screen_analytics_prompt_third_party_sharing">"Não partilharemos os teus dados com terceiros"</string>
|
||||||
|
<string name="screen_analytics_prompt_title">"Ajude a melhorar a %1$s"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_analytics_prompt_data_usage">"我们不会记录或分析任何个人数据"</string>
|
||||||
|
<string name="screen_analytics_prompt_help_us_improve">"共享匿名使用数据以帮助我们排查问题。"</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms">"您可以阅读我们的所有条款 %1$s。"</string>
|
||||||
|
<string name="screen_analytics_prompt_read_terms_content_link">"此处"</string>
|
||||||
|
<string name="screen_analytics_prompt_settings">"你可以随时关闭此功能"</string>
|
||||||
|
<string name="screen_analytics_prompt_third_party_sharing">"我们不会与第三方共享您的数据"</string>
|
||||||
|
<string name="screen_analytics_prompt_title">"帮助改进 %1$s"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -72,15 +72,10 @@ class CallForegroundService : Service() {
|
||||||
startForeground(1, notification)
|
startForeground(1, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
|
||||||
} else {
|
|
||||||
stopForeground(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,12 @@ internal fun CallScreenView(
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
url = state.urlState,
|
url = state.urlState,
|
||||||
userAgent = state.userAgent,
|
userAgent = state.userAgent,
|
||||||
onPermissionsRequested = { request ->
|
onPermissionsRequest = { request ->
|
||||||
val androidPermissions = mapWebkitPermissions(request.resources)
|
val androidPermissions = mapWebkitPermissions(request.resources)
|
||||||
val callback: RequestPermissionCallback = { request.grant(it) }
|
val callback: RequestPermissionCallback = { request.grant(it) }
|
||||||
requestPermissions(androidPermissions.toTypedArray(), callback)
|
requestPermissions(androidPermissions.toTypedArray(), callback)
|
||||||
},
|
},
|
||||||
onWebViewCreated = { webView ->
|
onWebViewCreate = { webView ->
|
||||||
val interceptor = WebViewWidgetMessageInterceptor(webView)
|
val interceptor = WebViewWidgetMessageInterceptor(webView)
|
||||||
state.eventSink(CallScreenEvents.SetupMessageChannels(interceptor))
|
state.eventSink(CallScreenEvents.SetupMessageChannels(interceptor))
|
||||||
}
|
}
|
||||||
|
|
@ -98,8 +98,8 @@ internal fun CallScreenView(
|
||||||
private fun CallWebView(
|
private fun CallWebView(
|
||||||
url: AsyncData<String>,
|
url: AsyncData<String>,
|
||||||
userAgent: String,
|
userAgent: String,
|
||||||
onPermissionsRequested: (PermissionRequest) -> Unit,
|
onPermissionsRequest: (PermissionRequest) -> Unit,
|
||||||
onWebViewCreated: (WebView) -> Unit,
|
onWebViewCreate: (WebView) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
if (LocalInspectionMode.current) {
|
if (LocalInspectionMode.current) {
|
||||||
|
|
@ -111,8 +111,8 @@ private fun CallWebView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
factory = { context ->
|
factory = { context ->
|
||||||
WebView(context).apply {
|
WebView(context).apply {
|
||||||
onWebViewCreated(this)
|
onWebViewCreate(this)
|
||||||
setup(userAgent, onPermissionsRequested)
|
setup(userAgent, onPermissionsRequest)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { webView ->
|
update = { webView ->
|
||||||
|
|
|
||||||
6
features/call/src/main/res/values-ka/translations.xml
Normal file
6
features/call/src/main/res/values-ka/translations.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="call_foreground_service_channel_title_android">"მიმდინარე ზარი"</string>
|
||||||
|
<string name="call_foreground_service_message_android">"დააწკაპუნეთ ზარში დასაბრუნებლად"</string>
|
||||||
|
<string name="call_foreground_service_title_android">"☎️ ზარი მიმდინარეობს"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="call_foreground_service_channel_title_android">"Chamada em curso"</string>
|
||||||
|
<string name="call_foreground_service_message_android">"Toca para voltar à chamada"</string>
|
||||||
|
<string name="call_foreground_service_title_android">"☎️ Chamada em curso"</string>
|
||||||
|
</resources>
|
||||||
6
features/call/src/main/res/values-zh/translations.xml
Normal file
6
features/call/src/main/res/values-zh/translations.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="call_foreground_service_channel_title_android">"通话进行中"</string>
|
||||||
|
<string name="call_foreground_service_message_android">"点按即可返回通话"</string>
|
||||||
|
<string name="call_foreground_service_title_android">"☎️ 通话中"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -30,7 +30,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
||||||
import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
|
import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver
|
||||||
import io.element.android.libraries.network.useragent.UserAgentProvider
|
import io.element.android.libraries.network.useragent.UserAgentProvider
|
||||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
|
|
@ -68,7 +68,7 @@ class CallScreenPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - with CallType RoomCall loads URL and runs WidgetDriver`() = runTest {
|
fun `present - with CallType RoomCall loads URL and runs WidgetDriver`() = runTest {
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val widgetProvider = FakeCallWidgetProvider(widgetDriver)
|
val widgetProvider = FakeCallWidgetProvider(widgetDriver)
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
|
|
@ -91,7 +91,7 @@ class CallScreenPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - set message interceptor, send and receive messages`() = runTest {
|
fun `present - set message interceptor, send and receive messages`() = runTest {
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
widgetDriver = widgetDriver,
|
widgetDriver = widgetDriver,
|
||||||
|
|
@ -119,7 +119,7 @@ class CallScreenPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - hang up event closes the screen and stops the widget driver`() = runTest(UnconfinedTestDispatcher()) {
|
fun `present - hang up event closes the screen and stops the widget driver`() = runTest(UnconfinedTestDispatcher()) {
|
||||||
val navigator = FakeCallScreenNavigator()
|
val navigator = FakeCallScreenNavigator()
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
widgetDriver = widgetDriver,
|
widgetDriver = widgetDriver,
|
||||||
|
|
@ -149,7 +149,7 @@ class CallScreenPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - a received hang up message closes the screen and stops the widget driver`() = runTest(UnconfinedTestDispatcher()) {
|
fun `present - a received hang up message closes the screen and stops the widget driver`() = runTest(UnconfinedTestDispatcher()) {
|
||||||
val navigator = FakeCallScreenNavigator()
|
val navigator = FakeCallScreenNavigator()
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
widgetDriver = widgetDriver,
|
widgetDriver = widgetDriver,
|
||||||
|
|
@ -178,7 +178,7 @@ class CallScreenPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - automatically starts the Matrix client sync when on RoomCall`() = runTest {
|
fun `present - automatically starts the Matrix client sync when on RoomCall`() = runTest {
|
||||||
val navigator = FakeCallScreenNavigator()
|
val navigator = FakeCallScreenNavigator()
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val matrixClient = FakeMatrixClient()
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
|
|
@ -201,7 +201,7 @@ class CallScreenPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - automatically stops the Matrix client sync on dispose`() = runTest {
|
fun `present - automatically stops the Matrix client sync on dispose`() = runTest {
|
||||||
val navigator = FakeCallScreenNavigator()
|
val navigator = FakeCallScreenNavigator()
|
||||||
val widgetDriver = FakeWidgetDriver()
|
val widgetDriver = FakeMatrixWidgetDriver()
|
||||||
val matrixClient = FakeMatrixClient()
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = createCallScreenPresenter(
|
val presenter = createCallScreenPresenter(
|
||||||
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
|
||||||
|
|
@ -229,7 +229,7 @@ class CallScreenPresenterTest {
|
||||||
private fun TestScope.createCallScreenPresenter(
|
private fun TestScope.createCallScreenPresenter(
|
||||||
callType: CallType,
|
callType: CallType,
|
||||||
navigator: CallScreenNavigator = FakeCallScreenNavigator(),
|
navigator: CallScreenNavigator = FakeCallScreenNavigator(),
|
||||||
widgetDriver: FakeWidgetDriver = FakeWidgetDriver(),
|
widgetDriver: FakeMatrixWidgetDriver = FakeMatrixWidgetDriver(),
|
||||||
widgetProvider: FakeCallWidgetProvider = FakeCallWidgetProvider(widgetDriver),
|
widgetProvider: FakeCallWidgetProvider = FakeCallWidgetProvider(widgetDriver),
|
||||||
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
||||||
matrixClientsProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(),
|
matrixClientsProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(),
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
import io.element.android.libraries.matrix.test.widget.FakeCallWidgetSettingsProvider
|
import io.element.android.libraries.matrix.test.widget.FakeCallWidgetSettingsProvider
|
||||||
import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
|
import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver
|
||||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -76,7 +76,7 @@ class DefaultCallWidgetProviderTest {
|
||||||
fun `getWidget - returns a widget driver when all steps are successful`() = runTest {
|
fun `getWidget - returns a widget driver when all steps are successful`() = runTest {
|
||||||
val room = FakeMatrixRoom().apply {
|
val room = FakeMatrixRoom().apply {
|
||||||
givenGenerateWidgetWebViewUrlResult(Result.success("url"))
|
givenGenerateWidgetWebViewUrlResult(Result.success("url"))
|
||||||
givenGetWidgetDriverResult(Result.success(FakeWidgetDriver()))
|
givenGetWidgetDriverResult(Result.success(FakeMatrixWidgetDriver()))
|
||||||
}
|
}
|
||||||
val client = FakeMatrixClient().apply {
|
val client = FakeMatrixClient().apply {
|
||||||
givenGetRoomResult(A_ROOM_ID, room)
|
givenGetRoomResult(A_ROOM_ID, room)
|
||||||
|
|
@ -89,7 +89,7 @@ class DefaultCallWidgetProviderTest {
|
||||||
fun `getWidget - will use a custom base url if it exists`() = runTest {
|
fun `getWidget - will use a custom base url if it exists`() = runTest {
|
||||||
val room = FakeMatrixRoom().apply {
|
val room = FakeMatrixRoom().apply {
|
||||||
givenGenerateWidgetWebViewUrlResult(Result.success("url"))
|
givenGenerateWidgetWebViewUrlResult(Result.success("url"))
|
||||||
givenGetWidgetDriverResult(Result.success(FakeWidgetDriver()))
|
givenGetWidgetDriverResult(Result.success(FakeMatrixWidgetDriver()))
|
||||||
}
|
}
|
||||||
val client = FakeMatrixClient().apply {
|
val client = FakeMatrixClient().apply {
|
||||||
givenGetRoomResult(A_ROOM_ID, room)
|
givenGetRoomResult(A_ROOM_ID, room)
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,10 @@ package io.element.android.features.call.utils
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||||
import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
|
import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver
|
||||||
|
|
||||||
class FakeCallWidgetProvider(
|
class FakeCallWidgetProvider(
|
||||||
private val widgetDriver: FakeWidgetDriver = FakeWidgetDriver(),
|
private val widgetDriver: FakeMatrixWidgetDriver = FakeMatrixWidgetDriver(),
|
||||||
private val url: String = "https://call.element.io",
|
private val url: String = "https://call.element.io",
|
||||||
) : CallWidgetProvider {
|
) : CallWidgetProvider {
|
||||||
var getWidgetCalled = false
|
var getWidgetCalled = false
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ class AddPeopleNode @AssistedInject constructor(
|
||||||
AddPeopleView(
|
AddPeopleView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackPressed = this::navigateUp,
|
onBackClick = this::navigateUp,
|
||||||
onNextPressed = this::onContinue,
|
onNextClick = this::onContinue,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@Composable
|
@Composable
|
||||||
fun AddPeopleView(
|
fun AddPeopleView(
|
||||||
state: UserListState,
|
state: UserListState,
|
||||||
onBackPressed: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onNextPressed: () -> Unit,
|
onNextClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -51,14 +51,14 @@ fun AddPeopleView(
|
||||||
topBar = {
|
topBar = {
|
||||||
AddPeopleViewTopBar(
|
AddPeopleViewTopBar(
|
||||||
hasSelectedUsers = state.selectedUsers.isNotEmpty(),
|
hasSelectedUsers = state.selectedUsers.isNotEmpty(),
|
||||||
onBackPressed = {
|
onBackClick = {
|
||||||
if (state.isSearchActive) {
|
if (state.isSearchActive) {
|
||||||
state.eventSink(UserListEvents.OnSearchActiveChanged(false))
|
state.eventSink(UserListEvents.OnSearchActiveChanged(false))
|
||||||
} else {
|
} else {
|
||||||
onBackPressed()
|
onBackClick()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNextPressed = onNextPressed,
|
onNextClick = onNextClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
|
|
@ -69,8 +69,8 @@ fun AddPeopleView(
|
||||||
.consumeWindowInsets(padding),
|
.consumeWindowInsets(padding),
|
||||||
state = state,
|
state = state,
|
||||||
showBackButton = false,
|
showBackButton = false,
|
||||||
onUserSelected = {},
|
onSelectUser = {},
|
||||||
onUserDeselected = {},
|
onDeselectUser = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -79,8 +79,8 @@ fun AddPeopleView(
|
||||||
@Composable
|
@Composable
|
||||||
private fun AddPeopleViewTopBar(
|
private fun AddPeopleViewTopBar(
|
||||||
hasSelectedUsers: Boolean,
|
hasSelectedUsers: Boolean,
|
||||||
onBackPressed: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onNextPressed: () -> Unit,
|
onNextClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
|
|
@ -89,12 +89,12 @@ private fun AddPeopleViewTopBar(
|
||||||
style = ElementTheme.typography.aliasScreenTitle
|
style = ElementTheme.typography.aliasScreenTitle
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = { BackButton(onClick = onBackPressed) },
|
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||||
actions = {
|
actions = {
|
||||||
val textActionResId = if (hasSelectedUsers) CommonStrings.action_next else CommonStrings.action_skip
|
val textActionResId = if (hasSelectedUsers) CommonStrings.action_next else CommonStrings.action_skip
|
||||||
TextButton(
|
TextButton(
|
||||||
text = stringResource(id = textActionResId),
|
text = stringResource(id = textActionResId),
|
||||||
onClick = onNextPressed,
|
onClick = onNextClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -105,7 +105,7 @@ private fun AddPeopleViewTopBar(
|
||||||
internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvider::class) state: UserListState) = ElementPreview {
|
internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvider::class) state: UserListState) = ElementPreview {
|
||||||
AddPeopleView(
|
AddPeopleView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackPressed = {},
|
onBackClick = {},
|
||||||
onNextPressed = {},
|
onNextClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
@Composable
|
@Composable
|
||||||
fun RoomPrivacyOption(
|
fun RoomPrivacyOption(
|
||||||
roomPrivacyItem: RoomPrivacyItem,
|
roomPrivacyItem: RoomPrivacyItem,
|
||||||
onOptionSelected: (RoomPrivacyItem) -> Unit,
|
onOptionClick: (RoomPrivacyItem) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isSelected: Boolean = false,
|
isSelected: Boolean = false,
|
||||||
) {
|
) {
|
||||||
|
|
@ -50,7 +50,7 @@ fun RoomPrivacyOption(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.selectable(
|
.selectable(
|
||||||
selected = isSelected,
|
selected = isSelected,
|
||||||
onClick = { onOptionSelected(roomPrivacyItem) },
|
onClick = { onOptionClick(roomPrivacyItem) },
|
||||||
role = Role.RadioButton,
|
role = Role.RadioButton,
|
||||||
)
|
)
|
||||||
.padding(8.dp),
|
.padding(8.dp),
|
||||||
|
|
@ -98,12 +98,12 @@ internal fun RoomPrivacyOptionPreview() = ElementPreview {
|
||||||
Column {
|
Column {
|
||||||
RoomPrivacyOption(
|
RoomPrivacyOption(
|
||||||
roomPrivacyItem = aRoomPrivacyItem,
|
roomPrivacyItem = aRoomPrivacyItem,
|
||||||
onOptionSelected = {},
|
onOptionClick = {},
|
||||||
isSelected = true,
|
isSelected = true,
|
||||||
)
|
)
|
||||||
RoomPrivacyOption(
|
RoomPrivacyOption(
|
||||||
roomPrivacyItem = aRoomPrivacyItem,
|
roomPrivacyItem = aRoomPrivacyItem,
|
||||||
onOptionSelected = {},
|
onOptionClick = {},
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,11 @@ fun SearchUserBar(
|
||||||
showLoader: Boolean,
|
showLoader: Boolean,
|
||||||
selectedUsers: ImmutableList<MatrixUser>,
|
selectedUsers: ImmutableList<MatrixUser>,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isMultiSelectionEnabled: Boolean,
|
isMultiSelectionEnable: Boolean,
|
||||||
onActiveChanged: (Boolean) -> Unit,
|
onActiveChange: (Boolean) -> Unit,
|
||||||
onTextChanged: (String) -> Unit,
|
onTextChange: (String) -> Unit,
|
||||||
onUserSelected: (MatrixUser) -> Unit,
|
onUserSelect: (MatrixUser) -> Unit,
|
||||||
onUserDeselected: (MatrixUser) -> Unit,
|
onUserDeselect: (MatrixUser) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
showBackButton: Boolean = true,
|
showBackButton: Boolean = true,
|
||||||
placeHolderTitle: String = stringResource(CommonStrings.common_search_for_someone),
|
placeHolderTitle: String = stringResource(CommonStrings.common_search_for_someone),
|
||||||
|
|
@ -66,14 +66,14 @@ fun SearchUserBar(
|
||||||
|
|
||||||
SearchBar(
|
SearchBar(
|
||||||
query = query,
|
query = query,
|
||||||
onQueryChange = onTextChanged,
|
onQueryChange = onTextChange,
|
||||||
active = active,
|
active = active,
|
||||||
onActiveChange = onActiveChanged,
|
onActiveChange = onActiveChange,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
placeHolderTitle = placeHolderTitle,
|
placeHolderTitle = placeHolderTitle,
|
||||||
showBackButton = showBackButton,
|
showBackButton = showBackButton,
|
||||||
contentPrefix = {
|
contentPrefix = {
|
||||||
if (isMultiSelectionEnabled && active && selectedUsers.isNotEmpty()) {
|
if (isMultiSelectionEnable && active && selectedUsers.isNotEmpty()) {
|
||||||
// We want the selected users to behave a bit like a top bar - when the list below is scrolled, the colour
|
// We want the selected users to behave a bit like a top bar - when the list below is scrolled, the colour
|
||||||
// should change to indicate elevation.
|
// should change to indicate elevation.
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ fun SearchUserBar(
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(16.dp),
|
||||||
selectedUsers = selectedUsers,
|
selectedUsers = selectedUsers,
|
||||||
autoScroll = true,
|
autoScroll = true,
|
||||||
onUserRemoved = onUserDeselected,
|
onUserRemove = onUserDeselect,
|
||||||
modifier = Modifier.background(appBarContainerColor)
|
modifier = Modifier.background(appBarContainerColor)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ fun SearchUserBar(
|
||||||
resultState = state,
|
resultState = state,
|
||||||
resultHandler = { users ->
|
resultHandler = { users ->
|
||||||
LazyColumn(state = columnState) {
|
LazyColumn(state = columnState) {
|
||||||
if (isMultiSelectionEnabled) {
|
if (isMultiSelectionEnable) {
|
||||||
itemsIndexed(users) { index, searchResult ->
|
itemsIndexed(users) { index, searchResult ->
|
||||||
SearchMultipleUsersResultItem(
|
SearchMultipleUsersResultItem(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -117,9 +117,9 @@ fun SearchUserBar(
|
||||||
isUserSelected = selectedUsers.contains(searchResult.matrixUser),
|
isUserSelected = selectedUsers.contains(searchResult.matrixUser),
|
||||||
onCheckedChange = { checked ->
|
onCheckedChange = { checked ->
|
||||||
if (checked) {
|
if (checked) {
|
||||||
onUserSelected(searchResult.matrixUser)
|
onUserSelect(searchResult.matrixUser)
|
||||||
} else {
|
} else {
|
||||||
onUserDeselected(searchResult.matrixUser)
|
onUserDeselect(searchResult.matrixUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -132,7 +132,7 @@ fun SearchUserBar(
|
||||||
SearchSingleUserResultItem(
|
SearchSingleUserResultItem(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
searchResult = searchResult,
|
searchResult = searchResult,
|
||||||
onClick = { onUserSelected(searchResult.matrixUser) }
|
onClick = { onUserSelect(searchResult.matrixUser) }
|
||||||
)
|
)
|
||||||
if (index < users.lastIndex) {
|
if (index < users.lastIndex) {
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@Composable
|
@Composable
|
||||||
fun UserListView(
|
fun UserListView(
|
||||||
state: UserListState,
|
state: UserListState,
|
||||||
onUserSelected: (MatrixUser) -> Unit,
|
onSelectUser: (MatrixUser) -> Unit,
|
||||||
onUserDeselected: (MatrixUser) -> Unit,
|
onDeselectUser: (MatrixUser) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
showBackButton: Boolean = true,
|
showBackButton: Boolean = true,
|
||||||
) {
|
) {
|
||||||
|
|
@ -59,17 +59,17 @@ fun UserListView(
|
||||||
selectedUsers = state.selectedUsers,
|
selectedUsers = state.selectedUsers,
|
||||||
active = state.isSearchActive,
|
active = state.isSearchActive,
|
||||||
showLoader = state.showSearchLoader,
|
showLoader = state.showSearchLoader,
|
||||||
isMultiSelectionEnabled = state.isMultiSelectionEnabled,
|
isMultiSelectionEnable = state.isMultiSelectionEnabled,
|
||||||
showBackButton = showBackButton,
|
showBackButton = showBackButton,
|
||||||
onActiveChanged = { state.eventSink(UserListEvents.OnSearchActiveChanged(it)) },
|
onActiveChange = { state.eventSink(UserListEvents.OnSearchActiveChanged(it)) },
|
||||||
onTextChanged = { state.eventSink(UserListEvents.UpdateSearchQuery(it)) },
|
onTextChange = { state.eventSink(UserListEvents.UpdateSearchQuery(it)) },
|
||||||
onUserSelected = {
|
onUserSelect = {
|
||||||
state.eventSink(UserListEvents.AddToSelection(it))
|
state.eventSink(UserListEvents.AddToSelection(it))
|
||||||
onUserSelected(it)
|
onSelectUser(it)
|
||||||
},
|
},
|
||||||
onUserDeselected = {
|
onUserDeselect = {
|
||||||
state.eventSink(UserListEvents.RemoveFromSelection(it))
|
state.eventSink(UserListEvents.RemoveFromSelection(it))
|
||||||
onUserDeselected(it)
|
onDeselectUser(it)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -78,9 +78,9 @@ fun UserListView(
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(16.dp),
|
||||||
selectedUsers = state.selectedUsers,
|
selectedUsers = state.selectedUsers,
|
||||||
autoScroll = true,
|
autoScroll = true,
|
||||||
onUserRemoved = {
|
onUserRemove = {
|
||||||
state.eventSink(UserListEvents.RemoveFromSelection(it))
|
state.eventSink(UserListEvents.RemoveFromSelection(it))
|
||||||
onUserDeselected(it)
|
onDeselectUser(it)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -102,10 +102,10 @@ fun UserListView(
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
state.eventSink(UserListEvents.RemoveFromSelection(recentDirectRoom.matrixUser))
|
state.eventSink(UserListEvents.RemoveFromSelection(recentDirectRoom.matrixUser))
|
||||||
onUserDeselected(recentDirectRoom.matrixUser)
|
onDeselectUser(recentDirectRoom.matrixUser)
|
||||||
} else {
|
} else {
|
||||||
state.eventSink(UserListEvents.AddToSelection(recentDirectRoom.matrixUser))
|
state.eventSink(UserListEvents.AddToSelection(recentDirectRoom.matrixUser))
|
||||||
onUserSelected(recentDirectRoom.matrixUser)
|
onSelectUser(recentDirectRoom.matrixUser)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data = CheckableUserRowData.Resolved(
|
data = CheckableUserRowData.Resolved(
|
||||||
|
|
@ -129,7 +129,7 @@ fun UserListView(
|
||||||
internal fun UserListViewPreview(@PreviewParameter(UserListStateProvider::class) state: UserListState) = ElementPreview {
|
internal fun UserListViewPreview(@PreviewParameter(UserListStateProvider::class) state: UserListState) = ElementPreview {
|
||||||
UserListView(
|
UserListView(
|
||||||
state = state,
|
state = state,
|
||||||
onUserSelected = {},
|
onSelectUser = {},
|
||||||
onUserDeselected = {},
|
onDeselectUser = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class ConfigureRoomNode @AssistedInject constructor(
|
||||||
fun onCreateRoomSuccess(roomId: RoomId)
|
fun onCreateRoomSuccess(roomId: RoomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onRoomCreated(roomId: RoomId) {
|
private fun onCreateRoomSuccess(roomId: RoomId) {
|
||||||
plugins<Callback>().forEach { it.onCreateRoomSuccess(roomId) }
|
plugins<Callback>().forEach { it.onCreateRoomSuccess(roomId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,8 +60,8 @@ class ConfigureRoomNode @AssistedInject constructor(
|
||||||
ConfigureRoomView(
|
ConfigureRoomView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackPressed = this::navigateUp,
|
onBackClick = this::navigateUp,
|
||||||
onRoomCreated = this::onRoomCreated,
|
onCreateRoomSuccess = this::onCreateRoomSuccess,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,10 @@ import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.selection.selectableGroup
|
import androidx.compose.foundation.selection.selectableGroup
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
|
||||||
import androidx.compose.material.ModalBottomSheetValue
|
|
||||||
import androidx.compose.material.rememberModalBottomSheetState
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
|
|
@ -63,27 +61,20 @@ import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList
|
||||||
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
|
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
|
||||||
import io.element.android.libraries.permissions.api.PermissionsView
|
import io.element.android.libraries.permissions.api.PermissionsView
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ConfigureRoomView(
|
fun ConfigureRoomView(
|
||||||
state: ConfigureRoomState,
|
state: ConfigureRoomState,
|
||||||
onBackPressed: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onRoomCreated: (RoomId) -> Unit,
|
onCreateRoomSuccess: (RoomId) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val focusManager = LocalFocusManager.current
|
val focusManager = LocalFocusManager.current
|
||||||
val itemActionsBottomSheetState = rememberModalBottomSheetState(
|
val isAvatarActionsSheetVisible = remember { mutableStateOf(false) }
|
||||||
initialValue = ModalBottomSheetValue.Hidden,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun onAvatarClicked() {
|
fun onAvatarClick() {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
coroutineScope.launch {
|
isAvatarActionsSheetVisible.value = true
|
||||||
itemActionsBottomSheetState.show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -91,8 +82,8 @@ fun ConfigureRoomView(
|
||||||
topBar = {
|
topBar = {
|
||||||
ConfigureRoomToolbar(
|
ConfigureRoomToolbar(
|
||||||
isNextActionEnabled = state.isCreateButtonEnabled,
|
isNextActionEnabled = state.isCreateButtonEnabled,
|
||||||
onBackPressed = onBackPressed,
|
onBackClick = onBackClick,
|
||||||
onNextPressed = {
|
onNextClick = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
state.eventSink(ConfigureRoomEvents.CreateRoom(state.config))
|
state.eventSink(ConfigureRoomEvents.CreateRoom(state.config))
|
||||||
},
|
},
|
||||||
|
|
@ -111,20 +102,20 @@ fun ConfigureRoomView(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
avatarUri = state.config.avatarUri,
|
avatarUri = state.config.avatarUri,
|
||||||
roomName = state.config.roomName.orEmpty(),
|
roomName = state.config.roomName.orEmpty(),
|
||||||
onAvatarClick = ::onAvatarClicked,
|
onAvatarClick = ::onAvatarClick,
|
||||||
onRoomNameChanged = { state.eventSink(ConfigureRoomEvents.RoomNameChanged(it)) },
|
onChangeRoomName = { state.eventSink(ConfigureRoomEvents.RoomNameChanged(it)) },
|
||||||
)
|
)
|
||||||
RoomTopic(
|
RoomTopic(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
topic = state.config.topic.orEmpty(),
|
topic = state.config.topic.orEmpty(),
|
||||||
onTopicChanged = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) },
|
onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) },
|
||||||
)
|
)
|
||||||
if (state.config.invites.isNotEmpty()) {
|
if (state.config.invites.isNotEmpty()) {
|
||||||
SelectedUsersRowList(
|
SelectedUsersRowList(
|
||||||
modifier = Modifier.padding(bottom = 16.dp),
|
modifier = Modifier.padding(bottom = 16.dp),
|
||||||
contentPadding = PaddingValues(horizontal = 24.dp),
|
contentPadding = PaddingValues(horizontal = 24.dp),
|
||||||
selectedUsers = state.config.invites,
|
selectedUsers = state.config.invites,
|
||||||
onUserRemoved = {
|
onUserRemove = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
state.eventSink(ConfigureRoomEvents.RemoveFromSelection(it))
|
state.eventSink(ConfigureRoomEvents.RemoveFromSelection(it))
|
||||||
},
|
},
|
||||||
|
|
@ -133,7 +124,7 @@ fun ConfigureRoomView(
|
||||||
RoomPrivacyOptions(
|
RoomPrivacyOptions(
|
||||||
modifier = Modifier.padding(bottom = 40.dp),
|
modifier = Modifier.padding(bottom = 40.dp),
|
||||||
selected = state.config.privacy,
|
selected = state.config.privacy,
|
||||||
onOptionSelected = {
|
onOptionClick = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
state.eventSink(ConfigureRoomEvents.RoomPrivacyChanged(it.privacy))
|
state.eventSink(ConfigureRoomEvents.RoomPrivacyChanged(it.privacy))
|
||||||
},
|
},
|
||||||
|
|
@ -143,8 +134,9 @@ fun ConfigureRoomView(
|
||||||
|
|
||||||
AvatarActionBottomSheet(
|
AvatarActionBottomSheet(
|
||||||
actions = state.avatarActions,
|
actions = state.avatarActions,
|
||||||
modalBottomSheetState = itemActionsBottomSheetState,
|
isVisible = isAvatarActionsSheetVisible.value,
|
||||||
onActionSelected = { state.eventSink(ConfigureRoomEvents.HandleAvatarAction(it)) }
|
onDismiss = { isAvatarActionsSheetVisible.value = false },
|
||||||
|
onSelectAction = { state.eventSink(ConfigureRoomEvents.HandleAvatarAction(it)) }
|
||||||
)
|
)
|
||||||
|
|
||||||
AsyncActionView(
|
AsyncActionView(
|
||||||
|
|
@ -154,7 +146,7 @@ fun ConfigureRoomView(
|
||||||
progressText = stringResource(CommonStrings.common_creating_room),
|
progressText = stringResource(CommonStrings.common_creating_room),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSuccess = { onRoomCreated(it) },
|
onSuccess = { onCreateRoomSuccess(it) },
|
||||||
errorMessage = { stringResource(R.string.screen_create_room_error_creating_room) },
|
errorMessage = { stringResource(R.string.screen_create_room_error_creating_room) },
|
||||||
onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom(state.config)) },
|
onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom(state.config)) },
|
||||||
onErrorDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) },
|
onErrorDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) },
|
||||||
|
|
@ -169,8 +161,8 @@ fun ConfigureRoomView(
|
||||||
@Composable
|
@Composable
|
||||||
private fun ConfigureRoomToolbar(
|
private fun ConfigureRoomToolbar(
|
||||||
isNextActionEnabled: Boolean,
|
isNextActionEnabled: Boolean,
|
||||||
onBackPressed: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onNextPressed: () -> Unit,
|
onNextClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
|
|
@ -179,12 +171,12 @@ private fun ConfigureRoomToolbar(
|
||||||
style = ElementTheme.typography.aliasScreenTitle,
|
style = ElementTheme.typography.aliasScreenTitle,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = { BackButton(onClick = onBackPressed) },
|
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||||
actions = {
|
actions = {
|
||||||
TextButton(
|
TextButton(
|
||||||
text = stringResource(CommonStrings.action_create),
|
text = stringResource(CommonStrings.action_create),
|
||||||
enabled = isNextActionEnabled,
|
enabled = isNextActionEnabled,
|
||||||
onClick = onNextPressed,
|
onClick = onNextClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -195,7 +187,7 @@ private fun RoomNameWithAvatar(
|
||||||
avatarUri: Uri?,
|
avatarUri: Uri?,
|
||||||
roomName: String,
|
roomName: String,
|
||||||
onAvatarClick: () -> Unit,
|
onAvatarClick: () -> Unit,
|
||||||
onRoomNameChanged: (String) -> Unit,
|
onChangeRoomName: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -213,7 +205,7 @@ private fun RoomNameWithAvatar(
|
||||||
value = roomName,
|
value = roomName,
|
||||||
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
onValueChange = onRoomNameChanged,
|
onValueChange = onChangeRoomName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +213,7 @@ private fun RoomNameWithAvatar(
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoomTopic(
|
private fun RoomTopic(
|
||||||
topic: String,
|
topic: String,
|
||||||
onTopicChanged: (String) -> Unit,
|
onTopicChange: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
LabelledTextField(
|
LabelledTextField(
|
||||||
|
|
@ -229,7 +221,7 @@ private fun RoomTopic(
|
||||||
label = stringResource(R.string.screen_create_room_topic_label),
|
label = stringResource(R.string.screen_create_room_topic_label),
|
||||||
value = topic,
|
value = topic,
|
||||||
placeholder = stringResource(CommonStrings.common_topic_placeholder),
|
placeholder = stringResource(CommonStrings.common_topic_placeholder),
|
||||||
onValueChange = onTopicChanged,
|
onValueChange = onTopicChange,
|
||||||
maxLines = 3,
|
maxLines = 3,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
capitalization = KeyboardCapitalization.Sentences,
|
capitalization = KeyboardCapitalization.Sentences,
|
||||||
|
|
@ -240,7 +232,7 @@ private fun RoomTopic(
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoomPrivacyOptions(
|
private fun RoomPrivacyOptions(
|
||||||
selected: RoomPrivacy?,
|
selected: RoomPrivacy?,
|
||||||
onOptionSelected: (RoomPrivacyItem) -> Unit,
|
onOptionClick: (RoomPrivacyItem) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val items = roomPrivacyItems()
|
val items = roomPrivacyItems()
|
||||||
|
|
@ -249,7 +241,7 @@ private fun RoomPrivacyOptions(
|
||||||
RoomPrivacyOption(
|
RoomPrivacyOption(
|
||||||
roomPrivacyItem = item,
|
roomPrivacyItem = item,
|
||||||
isSelected = selected == item.privacy,
|
isSelected = selected == item.privacy,
|
||||||
onOptionSelected = onOptionSelected,
|
onOptionClick = onOptionClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +252,7 @@ private fun RoomPrivacyOptions(
|
||||||
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
|
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
|
||||||
ConfigureRoomView(
|
ConfigureRoomView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackPressed = {},
|
onBackClick = {},
|
||||||
onRoomCreated = {},
|
onCreateRoomSuccess = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,10 @@ class CreateRoomRootNode @AssistedInject constructor(
|
||||||
CreateRoomRootView(
|
CreateRoomRootView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onClosePressed = this::navigateUp,
|
onCloseClick = this::navigateUp,
|
||||||
onNewRoomClicked = ::onCreateNewRoom,
|
onNewRoomClick = ::onCreateNewRoom,
|
||||||
onOpenDM = ::onStartChatSuccess,
|
onOpenDM = ::onStartChatSuccess,
|
||||||
onInviteFriendsClicked = { invitePeople(activity) }
|
onInviteFriendsClick = { invitePeople(activity) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,17 +59,17 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
@Composable
|
@Composable
|
||||||
fun CreateRoomRootView(
|
fun CreateRoomRootView(
|
||||||
state: CreateRoomRootState,
|
state: CreateRoomRootState,
|
||||||
onClosePressed: () -> Unit,
|
onCloseClick: () -> Unit,
|
||||||
onNewRoomClicked: () -> Unit,
|
onNewRoomClick: () -> Unit,
|
||||||
onOpenDM: (RoomId) -> Unit,
|
onOpenDM: (RoomId) -> Unit,
|
||||||
onInviteFriendsClicked: () -> Unit,
|
onInviteFriendsClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier.fillMaxWidth(),
|
modifier = modifier.fillMaxWidth(),
|
||||||
topBar = {
|
topBar = {
|
||||||
if (!state.userListState.isSearchActive) {
|
if (!state.userListState.isSearchActive) {
|
||||||
CreateRoomRootViewTopBar(onClosePressed = onClosePressed)
|
CreateRoomRootViewTopBar(onCloseClick = onCloseClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
|
@ -86,18 +86,18 @@ fun CreateRoomRootView(
|
||||||
state = state.userListState.copy(
|
state = state.userListState.copy(
|
||||||
recentDirectRooms = persistentListOf(),
|
recentDirectRooms = persistentListOf(),
|
||||||
),
|
),
|
||||||
onUserSelected = {
|
onSelectUser = {
|
||||||
state.eventSink(CreateRoomRootEvents.StartDM(it))
|
state.eventSink(CreateRoomRootEvents.StartDM(it))
|
||||||
},
|
},
|
||||||
onUserDeselected = { },
|
onDeselectUser = { },
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!state.userListState.isSearchActive) {
|
if (!state.userListState.isSearchActive) {
|
||||||
CreateRoomActionButtonsList(
|
CreateRoomActionButtonsList(
|
||||||
state = state,
|
state = state,
|
||||||
onNewRoomClicked = onNewRoomClicked,
|
onNewRoomClick = onNewRoomClick,
|
||||||
onInvitePeopleClicked = onInviteFriendsClicked,
|
onInvitePeopleClick = onInviteFriendsClick,
|
||||||
onDmClicked = onOpenDM,
|
onDmClick = onOpenDM,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ fun CreateRoomRootView(
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun CreateRoomRootViewTopBar(
|
private fun CreateRoomRootViewTopBar(
|
||||||
onClosePressed: () -> Unit,
|
onCloseClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
|
|
@ -137,7 +137,7 @@ private fun CreateRoomRootViewTopBar(
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
BackButton(
|
BackButton(
|
||||||
imageVector = CompoundIcons.Close(),
|
imageVector = CompoundIcons.Close(),
|
||||||
onClick = onClosePressed,
|
onClick = onCloseClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -146,23 +146,23 @@ private fun CreateRoomRootViewTopBar(
|
||||||
@Composable
|
@Composable
|
||||||
private fun CreateRoomActionButtonsList(
|
private fun CreateRoomActionButtonsList(
|
||||||
state: CreateRoomRootState,
|
state: CreateRoomRootState,
|
||||||
onNewRoomClicked: () -> Unit,
|
onNewRoomClick: () -> Unit,
|
||||||
onInvitePeopleClicked: () -> Unit,
|
onInvitePeopleClick: () -> Unit,
|
||||||
onDmClicked: (RoomId) -> Unit,
|
onDmClick: (RoomId) -> Unit,
|
||||||
) {
|
) {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
item {
|
item {
|
||||||
CreateRoomActionButton(
|
CreateRoomActionButton(
|
||||||
iconRes = CompoundDrawables.ic_compound_plus,
|
iconRes = CompoundDrawables.ic_compound_plus,
|
||||||
text = stringResource(id = R.string.screen_create_room_action_create_room),
|
text = stringResource(id = R.string.screen_create_room_action_create_room),
|
||||||
onClick = onNewRoomClicked,
|
onClick = onNewRoomClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
CreateRoomActionButton(
|
CreateRoomActionButton(
|
||||||
iconRes = CompoundDrawables.ic_compound_share_android,
|
iconRes = CompoundDrawables.ic_compound_share_android,
|
||||||
text = stringResource(id = CommonStrings.action_invite_friends_to_app, state.applicationName),
|
text = stringResource(id = CommonStrings.action_invite_friends_to_app, state.applicationName),
|
||||||
onClick = onInvitePeopleClicked,
|
onClick = onInvitePeopleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (state.userListState.recentDirectRooms.isNotEmpty()) {
|
if (state.userListState.recentDirectRooms.isNotEmpty()) {
|
||||||
|
|
@ -177,7 +177,7 @@ private fun CreateRoomActionButtonsList(
|
||||||
MatrixUserRow(
|
MatrixUserRow(
|
||||||
modifier = Modifier.clickable(
|
modifier = Modifier.clickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDmClicked(recentDirectRoom.roomId)
|
onDmClick(recentDirectRoom.roomId)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
matrixUser = recentDirectRoom.matrixUser,
|
matrixUser = recentDirectRoom.matrixUser,
|
||||||
|
|
@ -222,9 +222,9 @@ internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProv
|
||||||
ElementPreview {
|
ElementPreview {
|
||||||
CreateRoomRootView(
|
CreateRoomRootView(
|
||||||
state = state,
|
state = state,
|
||||||
onClosePressed = {},
|
onCloseClick = {},
|
||||||
onNewRoomClicked = {},
|
onNewRoomClick = {},
|
||||||
onOpenDM = {},
|
onOpenDM = {},
|
||||||
onInviteFriendsClicked = {},
|
onInviteFriendsClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_create_room_action_create_room">"ახალი ოთახი"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"ხალხის მოწვევა"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"ოთახის შექმნისას შეცდომა მოხდა"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"ამ ოთახში შეტყობინებები დაშიფრულია. შემდგომ დაშიფვრის გამორთვა შეუძლებელია."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"კერძო ოთახი (მხოლოდ მოწვევა)"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"შეტყობინებები არ არის დაშიფრული და ყველას შეუძლია მათი წაკითხვა. შეგიძლიათ ჩართოთ დაშიფვრა მოგვიანებით."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"საჯარო ოთახი (ნებისმიერი)"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"ოთახის სახელი"</string>
|
||||||
|
<string name="screen_create_room_title">"ოთახის შექმნა"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"თემა (სურვილისამებრ)"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"ჩატის დაწყების მცდელობისას შეცდომა მოხდა"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_create_room_action_create_room">"Nova sala"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Convidar pessoas"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Ocorreu um erro ao criar a sala"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"As mensagens serão cifradas. Uma vez ativada, não é possível desativar a cifragem."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Sala privada (entrada apenas por convite)"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"As mensagens não serão cifradas e qualquer um as poderá ler. É possível ativar a cifragem posteriormente."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Sala pública (entrada livre)"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nome da sala"</string>
|
||||||
|
<string name="screen_create_room_title">"Criar uma sala"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Descrição (opcional)"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Ocorreu um erro ao tentar iniciar uma conversa"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_create_room_action_create_room">"新聊天室"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"邀请朋友"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"创建房间时出错"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"此聊天室中的消息已加密。加密无法禁用。"</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"私人房间(仅限受邀者)"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"消息未加密,任何人都可以查看。你可以稍后启用加密。"</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"公共房间(任何人)"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"房间名称"</string>
|
||||||
|
<string name="screen_create_room_title">"创建房间"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"主题(可选)"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"在开始聊天时发生了错误"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -47,7 +47,7 @@ class AddPeopleViewTest {
|
||||||
aUserListState(
|
aUserListState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
onBackPressed = it
|
onBackClick = it
|
||||||
)
|
)
|
||||||
rule.pressBack()
|
rule.pressBack()
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ class AddPeopleViewTest {
|
||||||
aUserListState(
|
aUserListState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
onNextPressed = it
|
onNextClick = it
|
||||||
)
|
)
|
||||||
rule.clickOn(CommonStrings.action_skip)
|
rule.clickOn(CommonStrings.action_skip)
|
||||||
}
|
}
|
||||||
|
|
@ -85,14 +85,14 @@ class AddPeopleViewTest {
|
||||||
|
|
||||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setAddPeopleView(
|
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setAddPeopleView(
|
||||||
state: UserListState,
|
state: UserListState,
|
||||||
onBackPressed: () -> Unit = EnsureNeverCalled(),
|
onBackClick: () -> Unit = EnsureNeverCalled(),
|
||||||
onNextPressed: () -> Unit = EnsureNeverCalled(),
|
onNextClick: () -> Unit = EnsureNeverCalled(),
|
||||||
) {
|
) {
|
||||||
setContent {
|
setContent {
|
||||||
AddPeopleView(
|
AddPeopleView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackPressed = onBackPressed,
|
onBackClick = onBackClick,
|
||||||
onNextPressed = onNextPressed,
|
onNextClick = onNextClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class CreateRoomRootViewTest {
|
||||||
aCreateRoomRootState(
|
aCreateRoomRootState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
onClosePressed = it
|
onCloseClick = it
|
||||||
)
|
)
|
||||||
rule.pressBack()
|
rule.pressBack()
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +68,7 @@ class CreateRoomRootViewTest {
|
||||||
aCreateRoomRootState(
|
aCreateRoomRootState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
onNewRoomClicked = it
|
onNewRoomClick = it
|
||||||
)
|
)
|
||||||
rule.clickOn(R.string.screen_create_room_action_create_room)
|
rule.clickOn(R.string.screen_create_room_action_create_room)
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ class CreateRoomRootViewTest {
|
||||||
applicationName = "test",
|
applicationName = "test",
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
onInviteFriendsClicked = it
|
onInviteFriendsClick = it
|
||||||
)
|
)
|
||||||
val text = rule.activity.getString(CommonStrings.action_invite_friends_to_app, "test")
|
val text = rule.activity.getString(CommonStrings.action_invite_friends_to_app, "test")
|
||||||
rule.onNodeWithText(text).performClick()
|
rule.onNodeWithText(text).performClick()
|
||||||
|
|
@ -114,18 +114,18 @@ class CreateRoomRootViewTest {
|
||||||
|
|
||||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCreateRoomRootView(
|
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCreateRoomRootView(
|
||||||
state: CreateRoomRootState,
|
state: CreateRoomRootState,
|
||||||
onClosePressed: () -> Unit = EnsureNeverCalled(),
|
onCloseClick: () -> Unit = EnsureNeverCalled(),
|
||||||
onNewRoomClicked: () -> Unit = EnsureNeverCalled(),
|
onNewRoomClick: () -> Unit = EnsureNeverCalled(),
|
||||||
onOpenDM: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
onOpenDM: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
||||||
onInviteFriendsClicked: () -> Unit = EnsureNeverCalled(),
|
onInviteFriendsClick: () -> Unit = EnsureNeverCalled(),
|
||||||
) {
|
) {
|
||||||
setContent {
|
setContent {
|
||||||
CreateRoomRootView(
|
CreateRoomRootView(
|
||||||
state = state,
|
state = state,
|
||||||
onClosePressed = onClosePressed,
|
onCloseClick = onCloseClick,
|
||||||
onNewRoomClicked = onNewRoomClicked,
|
onNewRoomClick = onNewRoomClick,
|
||||||
onOpenDM = onOpenDM,
|
onOpenDM = onOpenDM,
|
||||||
onInviteFriendsClicked = onInviteFriendsClicked,
|
onInviteFriendsClick = onInviteFriendsClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,8 @@ class FtueFlowNode @AssistedInject constructor(
|
||||||
lifecycleScope.launch { moveToNextStep() }
|
lifecycleScope.launch { moveToNextStep() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lockScreenEntryPoint.nodeBuilder(this, buildContext)
|
lockScreenEntryPoint.nodeBuilder(this, buildContext, LockScreenEntryPoint.Target.Setup)
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
.target(LockScreenEntryPoint.Target.Setup)
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,18 +34,18 @@ class WelcomeNode @AssistedInject constructor(
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onContinueClicked()
|
fun onContinueClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onContinueClicked() {
|
private fun onContinueClick() {
|
||||||
plugins.filterIsInstance<Callback>().forEach { it.onContinueClicked() }
|
plugins.filterIsInstance<Callback>().forEach { it.onContinueClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
WelcomeView(
|
WelcomeView(
|
||||||
applicationName = buildMeta.applicationName,
|
applicationName = buildMeta.applicationName,
|
||||||
onContinueClicked = ::onContinueClicked,
|
onContinueClick = ::onContinueClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
fun WelcomeView(
|
fun WelcomeView(
|
||||||
applicationName: String,
|
applicationName: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onContinueClicked: () -> Unit,
|
onContinueClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
BackHandler(onBack = onContinueClicked)
|
BackHandler(onBack = onContinueClick)
|
||||||
OnBoardingPage(
|
OnBoardingPage(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.systemBarsPadding()
|
.systemBarsPadding()
|
||||||
|
|
@ -90,7 +90,7 @@ fun WelcomeView(
|
||||||
Button(
|
Button(
|
||||||
text = stringResource(CommonStrings.action_continue),
|
text = stringResource(CommonStrings.action_continue),
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
onClick = onContinueClicked
|
onClick = onContinueClick
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +113,6 @@ private fun listItems() = persistentListOf(
|
||||||
@Composable
|
@Composable
|
||||||
internal fun WelcomeViewPreview() {
|
internal fun WelcomeViewPreview() {
|
||||||
ElementPreview {
|
ElementPreview {
|
||||||
WelcomeView(applicationName = "Element X", onContinueClicked = {})
|
WelcomeView(applicationName = "Element X", onContinueClick = {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,24 @@
|
||||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"Злучэнне небяспечнае"</string>
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"Злучэнне небяспечнае"</string>
|
||||||
<string name="screen_qr_code_login_device_code_subtitle">"Вам будзе прапанавана ўвесці дзве лічбы, паказаныя на гэтай прыладзе."</string>
|
<string name="screen_qr_code_login_device_code_subtitle">"Вам будзе прапанавана ўвесці дзве лічбы, паказаныя на гэтай прыладзе."</string>
|
||||||
<string name="screen_qr_code_login_device_code_title">"Увядзіце наступны нумар на іншай прыладзе."</string>
|
<string name="screen_qr_code_login_device_code_title">"Увядзіце наступны нумар на іншай прыладзе."</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_subtitle">"Уваход быў адменены на іншай прыладзе."</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_title">"Запыт на ўваход скасаваны"</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_subtitle">"Запыт на іншай прыладзе не быў прыняты."</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_title">"Уваход адхілены"</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_subtitle">"Тэрмін уваходу скончыўся. Калі ласка, паспрабуйце яшчэ раз."</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_title">"Уваход у сістэму не быў завершаны своечасова"</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Ваша іншая прылада не падтрымлівае ўваход у %s з дапамогай QR-кода.
|
||||||
|
|
||||||
|
Паспрабуйце ўвайсці ў сістэму ўручную або адскануйце QR-код з дапамогай іншай прылады."</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_title">"QR-код не падтрымліваецца"</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_subtitle">"Ваш правайдар уліковага запісу не падтрымлівае %1$s."</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_title">"%1$s не падтрымліваецца"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_button_title">"Гатовы да сканавання"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_1">"Адкрыйце %1$s на настольнай прыладзе"</string>
|
<string name="screen_qr_code_login_initial_state_item_1">"Адкрыйце %1$s на настольнай прыладзе"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_2">"Націсніце на свой аватар"</string>
|
<string name="screen_qr_code_login_initial_state_item_2">"Націсніце на свой аватар"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3">"Выберыце %1$s"</string>
|
<string name="screen_qr_code_login_initial_state_item_3">"Выберыце %1$s"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3_action">"“Звязаць новую прыладу”"</string>
|
<string name="screen_qr_code_login_initial_state_item_3_action">"“Звязаць новую прыладу”"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_4">"Выконвайце паказаныя інструкцыі"</string>
|
<string name="screen_qr_code_login_initial_state_item_4">"Адсканіруйце QR-код з дапамогай гэтай прылады"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_title">"Адкрыйце %1$s на іншай прыладзе, каб атрымаць QR-код"</string>
|
<string name="screen_qr_code_login_initial_state_title">"Адкрыйце %1$s на іншай прыладзе, каб атрымаць QR-код"</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Выкарыстоўвайце QR-код, паказаны на іншай прыладзе."</string>
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Выкарыстоўвайце QR-код, паказаны на іншай прыладзе."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Паўтарыць спробу"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Паўтарыць спробу"</string>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,24 @@
|
||||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"Připojení není zabezpečené"</string>
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"Připojení není zabezpečené"</string>
|
||||||
<string name="screen_qr_code_login_device_code_subtitle">"Budete požádáni o zadání dvou níže uvedených číslic."</string>
|
<string name="screen_qr_code_login_device_code_subtitle">"Budete požádáni o zadání dvou níže uvedených číslic."</string>
|
||||||
<string name="screen_qr_code_login_device_code_title">"Zadejte níže uvedené číslo na svém dalším zařízení"</string>
|
<string name="screen_qr_code_login_device_code_title">"Zadejte níže uvedené číslo na svém dalším zařízení"</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_subtitle">"Přihlášení bylo na druhém zařízení zrušeno."</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_title">"Žádost o přihlášení zrušena"</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_subtitle">"Požadavek na vašem druhém zařízení nebyl přijat."</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_title">"Přihlášení odmítnuto"</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_subtitle">"Platnost přihlášení vypršela. Zkuste to prosím znovu."</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_title">"Přihlášení nebylo dokončeno včas"</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Vaše druhé zařízení nepodporuje přihlášení k %su pomocí QR kódu.
|
||||||
|
|
||||||
|
Zkuste se přihlásit ručně nebo naskenujte QR kód pomocí jiného zařízení."</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_title">"QR kód není podporován"</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_subtitle">"Váš poskytovatel účtu nepodporuje %1$s."</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_title">"%1$s není podporováno"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_button_title">"Připraveno ke skenování"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_1">"Otevřete %1$s na stolním počítači"</string>
|
<string name="screen_qr_code_login_initial_state_item_1">"Otevřete %1$s na stolním počítači"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_2">"Klikněte na svůj avatar"</string>
|
<string name="screen_qr_code_login_initial_state_item_2">"Klikněte na svůj avatar"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3">"Vybrat %1$s"</string>
|
<string name="screen_qr_code_login_initial_state_item_3">"Vybrat %1$s"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Připojit nové zařízení\""</string>
|
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Připojit nové zařízení\""</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_4">"Postupujte podle uvedených pokynů"</string>
|
<string name="screen_qr_code_login_initial_state_item_4">"Naskenujte QR kód pomocí tohoto zařízení"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_title">"Otevřete %1$s na jiném zařízení pro získání QR kódu"</string>
|
<string name="screen_qr_code_login_initial_state_title">"Otevřete %1$s na jiném zařízení pro získání QR kódu"</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Použijte QR kód zobrazený na druhém zařízení."</string>
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Použijte QR kód zobrazený na druhém zařízení."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Zkusit znovu"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Zkusit znovu"</string>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@
|
||||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"Die Verbindung ist nicht sicher"</string>
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"Die Verbindung ist nicht sicher"</string>
|
||||||
<string name="screen_qr_code_login_device_code_subtitle">"Du wirst aufgefordert, die beiden unten abgebildeten Ziffern einzugeben."</string>
|
<string name="screen_qr_code_login_device_code_subtitle">"Du wirst aufgefordert, die beiden unten abgebildeten Ziffern einzugeben."</string>
|
||||||
<string name="screen_qr_code_login_device_code_title">"Trage die unten angezeigte Zahl auf einem anderen Device ein"</string>
|
<string name="screen_qr_code_login_device_code_title">"Trage die unten angezeigte Zahl auf einem anderen Device ein"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_button_title">"Bereit zum Scannen"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_1">"%1$s auf einem Desktop-Gerät öffnen"</string>
|
<string name="screen_qr_code_login_initial_state_item_1">"%1$s auf einem Desktop-Gerät öffnen"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_2">"Klick auf deinen Avatar"</string>
|
<string name="screen_qr_code_login_initial_state_item_2">"Klick auf deinen Avatar"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3">"Wähle %1$s"</string>
|
<string name="screen_qr_code_login_initial_state_item_3">"Wähle %1$s"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Neues Gerät verknüpfen\""</string>
|
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Neues Gerät verknüpfen\""</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_4">"Befolge die angezeigten Anweisungen"</string>
|
<string name="screen_qr_code_login_initial_state_item_4">"Scanne den QR-Code mit diesem Gerät"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_title">"Öffne %1$s auf einem anderen Gerät, um den QR-Code zu erhalten"</string>
|
<string name="screen_qr_code_login_initial_state_title">"Öffne %1$s auf einem anderen Gerät, um den QR-Code zu erhalten"</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Verwende den QR-Code, der auf dem anderen Gerät angezeigt wird."</string>
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Verwende den QR-Code, der auf dem anderen Gerät angezeigt wird."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Erneut versuchen"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Erneut versuchen"</string>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,22 @@
|
||||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"La connexion n’est pas sécurisée"</string>
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"La connexion n’est pas sécurisée"</string>
|
||||||
<string name="screen_qr_code_login_device_code_subtitle">"Il vous sera demandé de saisir les deux chiffres affichés sur cet appareil."</string>
|
<string name="screen_qr_code_login_device_code_subtitle">"Il vous sera demandé de saisir les deux chiffres affichés sur cet appareil."</string>
|
||||||
<string name="screen_qr_code_login_device_code_title">"Saisissez le nombre ci-dessous sur votre autre appareil"</string>
|
<string name="screen_qr_code_login_device_code_title">"Saisissez le nombre ci-dessous sur votre autre appareil"</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_subtitle">"La connexion a été annulée sur l’autre appareil."</string>
|
||||||
|
<string name="screen_qr_code_login_error_cancelled_title">"Demande de connexion annulée"</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_subtitle">"La demande sur l’autre appareil n’a pas été acceptée."</string>
|
||||||
|
<string name="screen_qr_code_login_error_declined_title">"Connexion refusée"</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_subtitle">"Connexion expirée. Veuillez essayer à nouveau."</string>
|
||||||
|
<string name="screen_qr_code_login_error_expired_title">"La connexion a pris trop de temps."</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Votre autre appareil ne supporte pas la connexion à %s avec un code QR. Essayer de vous connecter manuellement, ou scanner le code QR avec un autre appareil."</string>
|
||||||
|
<string name="screen_qr_code_login_error_linking_not_suported_title">"Code QR non supporté"</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_subtitle">"Votre fournisseur de compte ne supporte pas %1$s."</string>
|
||||||
|
<string name="screen_qr_code_login_error_sliding_sync_not_supported_title">"%1$s n’est pas supporté"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_button_title">"Prêt à scanner"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_1">"Ouvrez %1$s sur un ordinateur"</string>
|
<string name="screen_qr_code_login_initial_state_item_1">"Ouvrez %1$s sur un ordinateur"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_2">"Cliquez sur votre image de profil"</string>
|
<string name="screen_qr_code_login_initial_state_item_2">"Cliquez sur votre image de profil"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3">"Choisissez %1$s"</string>
|
<string name="screen_qr_code_login_initial_state_item_3">"Choisissez %1$s"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3_action">"“Associer une nouvelle session”"</string>
|
<string name="screen_qr_code_login_initial_state_item_3_action">"“Associer une nouvelle session”"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_4">"Suivez les instructions affichées"</string>
|
<string name="screen_qr_code_login_initial_state_item_4">"Scanner le code QR avec cet appareil"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_title">"Ouvrez %1$s sur un autre appareil pour obtenir le QR code"</string>
|
<string name="screen_qr_code_login_initial_state_title">"Ouvrez %1$s sur un autre appareil pour obtenir le QR code"</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Scannez le QR code affiché sur l’autre appareil."</string>
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Scannez le QR code affiché sur l’autre appareil."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Essayer à nouveau"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Essayer à nouveau"</string>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@
|
||||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"A kapcsolat nem biztonságos"</string>
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"A kapcsolat nem biztonságos"</string>
|
||||||
<string name="screen_qr_code_login_device_code_subtitle">"A rendszer kérni fogja, hogy adja meg az alábbi két számjegyet az eszközén."</string>
|
<string name="screen_qr_code_login_device_code_subtitle">"A rendszer kérni fogja, hogy adja meg az alábbi két számjegyet az eszközén."</string>
|
||||||
<string name="screen_qr_code_login_device_code_title">"Adja meg az alábbi számot a másik eszközén"</string>
|
<string name="screen_qr_code_login_device_code_title">"Adja meg az alábbi számot a másik eszközén"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_button_title">"Készen áll a beolvasásra"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_1">"Nyissa meg az %1$set egy asztali eszközön"</string>
|
<string name="screen_qr_code_login_initial_state_item_1">"Nyissa meg az %1$set egy asztali eszközön"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_2">"Kattintson a profilképére"</string>
|
<string name="screen_qr_code_login_initial_state_item_2">"Kattintson a profilképére"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3">"Válassza ezt: %1$s"</string>
|
<string name="screen_qr_code_login_initial_state_item_3">"Válassza ezt: %1$s"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_3_action">"„Új eszköz összekapcsolása”"</string>
|
<string name="screen_qr_code_login_initial_state_item_3_action">"„Új eszköz összekapcsolása”"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_item_4">"Kövesse a látható utasításokat"</string>
|
<string name="screen_qr_code_login_initial_state_item_4">"Olvassa be a QR-kódot ezzel az eszközzel"</string>
|
||||||
<string name="screen_qr_code_login_initial_state_title">"Nyissa meg az %1$set egy másik eszközön a QR-kód lekéréséhez."</string>
|
<string name="screen_qr_code_login_initial_state_title">"Nyissa meg az %1$set egy másik eszközön a QR-kód lekéréséhez."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Használja a másik eszközön látható QR-kódot."</string>
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Használja a másik eszközön látható QR-kódot."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Próbálja újra"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Próbálja újra"</string>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,33 @@
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="screen_notification_optin_subtitle">"Potrai modificare le tue impostazioni in seguito."</string>
|
<string name="screen_notification_optin_subtitle">"Potrai modificare le tue impostazioni in seguito."</string>
|
||||||
<string name="screen_notification_optin_title">"Consenti le notifiche e non perdere mai un messaggio"</string>
|
<string name="screen_notification_optin_title">"Consenti le notifiche e non perdere mai un messaggio"</string>
|
||||||
|
<string name="screen_qr_code_login_connecting_subtitle">"Stabilendo la connessione"</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_description">"Non è stato possibile stabilire una connessione sicura con il nuovo dispositivo. I tuoi dispositivi esistenti sono ancora al sicuro e non devi preoccuparti di loro."</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_list_header">"E adesso?"</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_list_item_1">"Prova ad accedere di nuovo con un codice QR nel caso si sia verificato un problema di rete."</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_list_item_2">"Se riscontri lo stesso problema, prova con un altra rete wifi o usa i dati mobili al posto del wifi."</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_list_item_3">"Se il problema persiste, accedi manualmente"</string>
|
||||||
|
<string name="screen_qr_code_login_connection_note_secure_state_title">"La connessione non è sicura"</string>
|
||||||
|
<string name="screen_qr_code_login_device_code_subtitle">"Ti verrà chiesto di inserire le due cifre mostrate su questo dispositivo."</string>
|
||||||
|
<string name="screen_qr_code_login_device_code_title">"Inserisci il numero qui sotto sull\'altro dispositivo"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_item_1">"Apri %1$s su un dispositivo desktop"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_item_2">"Clicca sul tuo avatar"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_item_3">"Seleziona %1$s"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Collega un nuovo dispositivo\""</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_item_4">"Segui le istruzioni mostrate"</string>
|
||||||
|
<string name="screen_qr_code_login_initial_state_title">"Apri %1$s su un altro dispositivo per ottenere il codice QR"</string>
|
||||||
|
<string name="screen_qr_code_login_invalid_scan_state_description">"Usa il codice QR mostrato sull\'altro dispositivo."</string>
|
||||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Riprova"</string>
|
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Riprova"</string>
|
||||||
|
<string name="screen_qr_code_login_invalid_scan_state_subtitle">"Codice QR sbagliato"</string>
|
||||||
|
<string name="screen_qr_code_login_no_camera_permission_button">"Vai alle impostazioni della fotocamera"</string>
|
||||||
|
<string name="screen_qr_code_login_no_camera_permission_state_description">"Per continuare, è necessario fornire l\'autorizzazione a %1$s per utilizzare la fotocamera del dispositivo."</string>
|
||||||
|
<string name="screen_qr_code_login_no_camera_permission_state_title">"Consenti l\'accesso alla fotocamera per la scansione del codice QR"</string>
|
||||||
|
<string name="screen_qr_code_login_scanning_state_title">"Scansiona il codice QR"</string>
|
||||||
|
<string name="screen_qr_code_login_start_over_button">"Ricomincia"</string>
|
||||||
|
<string name="screen_qr_code_login_unknown_error_description">"Si è verificato un errore inatteso. Riprova."</string>
|
||||||
|
<string name="screen_qr_code_login_verify_code_loading">"In attesa dell\'altro dispositivo"</string>
|
||||||
|
<string name="screen_qr_code_login_verify_code_subtitle">"Il fornitore dell\'account potrebbe richiedere il seguente codice per verificare l\'accesso."</string>
|
||||||
|
<string name="screen_qr_code_login_verify_code_title">"Il tuo codice di verifica"</string>
|
||||||
<string name="screen_welcome_bullet_1">"Chiamate, sondaggi, ricerche e altro ancora saranno aggiunti nel corso dell\'anno."</string>
|
<string name="screen_welcome_bullet_1">"Chiamate, sondaggi, ricerche e altro ancora saranno aggiunti nel corso dell\'anno."</string>
|
||||||
<string name="screen_welcome_bullet_2">"La cronologia dei messaggi per le stanze crittografate non è ancora disponibile."</string>
|
<string name="screen_welcome_bullet_2">"La cronologia dei messaggi per le stanze crittografate non è ancora disponibile."</string>
|
||||||
<string name="screen_welcome_bullet_3">"Ci piacerebbe sentire il tuo parere, facci sapere cosa ne pensi tramite la pagina delle impostazioni."</string>
|
<string name="screen_welcome_bullet_3">"Ci piacerebbe sentire il tuo parere, facci sapere cosa ne pensi tramite la pagina delle impostazioni."</string>
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue