Merge branch 'develop' into julioromano/poll_history_entry_point
This commit is contained in:
commit
863d156e4d
738 changed files with 9387 additions and 1581 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -1,2 +1,3 @@
|
|||
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text
|
||||
**/docs/images-lfs/*.png filter=lfs diff=lfs merge=lfs -text
|
||||
libraries/mediaupload/impl/src/test/assets/* filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -1,5 +1,5 @@
|
|||
name: Bug report for the Element X Android app
|
||||
description: Report any issues that you have found with the Element X app. Please [check open issues](https://github.com/vector-im/element-x-android/issues) first, in case it has already been reported.
|
||||
description: Report any issues that you have found with the Element X app. Please [check open issues](https://github.com/element-hq/element-x-android/issues) first, in case it has already been reported.
|
||||
labels: [T-Defect]
|
||||
body:
|
||||
- type: markdown
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
2
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
|
|
@ -5,7 +5,7 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/vector-im/element-meta/discussions/new?category=ideas).
|
||||
Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/element-hq/element-meta/discussions/new?category=ideas).
|
||||
- type: textarea
|
||||
id: usecase
|
||||
attributes:
|
||||
|
|
|
|||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
|
|
@ -13,7 +13,7 @@ updates:
|
|||
ignore:
|
||||
- dependency-name: "*"
|
||||
reviewers:
|
||||
- "vector-im/element-x-android-reviewers"
|
||||
- "element-hq/element-x-android-reviewers"
|
||||
# Updates for Gradle dependencies used in the app
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/"
|
||||
|
|
@ -23,4 +23,4 @@ updates:
|
|||
ignore:
|
||||
- dependency-name: "*"
|
||||
reviewers:
|
||||
- "vector-im/element-x-android-reviewers"
|
||||
- "element-hq/element-x-android-reviewers"
|
||||
|
|
|
|||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
|
|
@ -1,4 +1,4 @@
|
|||
<!-- Please read [CONTRIBUTING.md](https://github.com/vector-im/element-x-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->
|
||||
<!-- Please read [CONTRIBUTING.md](https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->
|
||||
|
||||
## Type of change
|
||||
|
||||
|
|
@ -53,9 +53,9 @@ Uncomment this markdown table below and edit the last line `|||`:
|
|||
|
||||
- [ ] Changes have been tested on an Android device or Android emulator with API 23
|
||||
- [ ] UI change has been tested on both light and dark themes
|
||||
- [ ] Accessibility has been taken into account. See https://github.com/vector-im/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
|
||||
- [ ] Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
|
||||
- [ ] Pull request is based on the develop branch
|
||||
- [ ] Pull request includes a new file under ./changelog.d. See https://github.com/vector-im/element-x-android/blob/develop/CONTRIBUTING.md#changelog
|
||||
- [ ] Pull request includes a new file under ./changelog.d. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#changelog
|
||||
- [ ] Pull request includes screenshots or videos if containing UI changes
|
||||
- [ ] Pull request includes a [sign off](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off)
|
||||
- [ ] You've made a self review of your PR
|
||||
|
|
|
|||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Assemble debug APK
|
||||
|
|
|
|||
2
.github/workflows/danger.yml
vendored
2
.github/workflows/danger.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
- run: |
|
||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||
- name: Danger
|
||||
uses: danger/danger-js@11.3.0
|
||||
uses: danger/danger-js@11.3.1
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile.js"
|
||||
env:
|
||||
|
|
|
|||
2
.github/workflows/gradle-wrapper-update.yml
vendored
2
.github/workflows/gradle-wrapper-update.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v1
|
||||
# Skip in forks
|
||||
if: github.repository == 'vector-im/element-x-android'
|
||||
if: github.repository == 'element-hq/element-x-android'
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-branch: develop
|
||||
|
|
|
|||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
nightly:
|
||||
name: Build and publish nightly bundle to Firebase
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'vector-im/element-x-android' }}
|
||||
if: ${{ github.repository == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use JDK 17
|
||||
|
|
|
|||
4
.github/workflows/nightlyReports.yml
vendored
4
.github/workflows/nightlyReports.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
nightlyReports:
|
||||
name: Create kover report artifact and upload sonar result.
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'vector-im/element-x-android' }}
|
||||
if: ${{ github.repository == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- name: ⏬ Checkout with LFS
|
||||
uses: nschloe/action-cached-lfs-checkout@v1.2.2
|
||||
|
|
@ -62,7 +62,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Dependency analysis
|
||||
|
|
|
|||
4
.github/workflows/quality.yml
vendored
4
.github/workflows/quality.yml
vendored
|
|
@ -40,7 +40,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Run code quality check suite
|
||||
|
|
@ -60,7 +60,7 @@ jobs:
|
|||
yarn add danger-plugin-lint-report --dev
|
||||
- name: Danger lint
|
||||
if: always()
|
||||
uses: danger/danger-js@11.3.0
|
||||
uses: danger/danger-js@11.3.1
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
|
||||
env:
|
||||
|
|
|
|||
2
.github/workflows/recordScreenshots.yml
vendored
2
.github/workflows/recordScreenshots.yml
vendored
|
|
@ -39,7 +39,7 @@ jobs:
|
|||
java-version: '17'
|
||||
# Add gradle cache, this should speed up the process
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Record screenshots
|
||||
|
|
|
|||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
- name: Create app bundle
|
||||
env:
|
||||
ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }}
|
||||
|
|
|
|||
2
.github/workflows/sonar.yml
vendored
2
.github/workflows/sonar.yml
vendored
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: 🔊 Publish results to Sonar
|
||||
|
|
|
|||
4
.github/workflows/sync-localazy.yml
vendored
4
.github/workflows/sync-localazy.yml
vendored
|
|
@ -9,11 +9,11 @@ jobs:
|
|||
sync-localazy:
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: github.repository == 'vector-im/element-x-android'
|
||||
if: github.repository == 'element-hq/element-x-android'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Setup Localazy
|
||||
|
|
|
|||
35
.github/workflows/sync-sas-strings.yml
vendored
Normal file
35
.github/workflows/sync-sas-strings.yml
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
name: Sync SAS strings
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# At 00:00 on every Monday UTC
|
||||
- cron: '0 0 * * 1'
|
||||
|
||||
jobs:
|
||||
sync-sas-strings:
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: github.repository == 'element-hq/element-x-android'
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install Prerequisite dependencies
|
||||
run: |
|
||||
pip install requests
|
||||
- name: Run SAS String script
|
||||
run: ./tools/sas/import_sas_strings.py
|
||||
- name: Create Pull Request for SAS Strings
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: Sync SAS Strings
|
||||
title: Sync SAS Strings
|
||||
body: |
|
||||
- Update SAS Strings from matrix-doc.
|
||||
branch: sync-sas-strings
|
||||
base: develop
|
||||
|
||||
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
|
|
@ -44,7 +44,7 @@ jobs:
|
|||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '17'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2.10.0
|
||||
uses: gradle/gradle-build-action@v2.11.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
|
||||
|
|
|
|||
2
.github/workflows/triage-incoming.yml
vendored
2
.github/workflows/triage-incoming.yml
vendored
|
|
@ -10,5 +10,5 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/91
|
||||
project-url: https://github.com/orgs/element-hq/projects/91
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
|
|
|||
16
.github/workflows/triage-labelled.yml
vendored
16
.github/workflows/triage-labelled.yml
vendored
|
|
@ -10,11 +10,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-x-android'
|
||||
github.repository == 'element-hq/element-x-android'
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/43
|
||||
project-url: https://github.com/orgs/element-hq/projects/43
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_needs_info:
|
||||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
- uses: actions/add-to-project@main
|
||||
id: addItem
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/91
|
||||
project-url: https://github.com/orgs/element-hq/projects/91
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
labeled: X-Needs-Info
|
||||
- name: Print itemId
|
||||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
- uses: kalgurn/update-project-item-status@main
|
||||
if: ${{ steps.addItem.outputs.itemId }}
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/91
|
||||
project-url: https://github.com/orgs/element-hq/projects/91
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
item-id: ${{ steps.addItem.outputs.itemId }}
|
||||
status: "Needs info"
|
||||
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/73
|
||||
project-url: https://github.com/orgs/element-hq/projects/73
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
verticals_feature:
|
||||
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/57
|
||||
project-url: https://github.com/orgs/element-hq/projects/57
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
qa:
|
||||
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/69
|
||||
project-url: https://github.com/orgs/element-hq/projects/69
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
signoff:
|
||||
|
|
@ -79,5 +79,5 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/89
|
||||
project-url: https://github.com/orgs/element-hq/projects/89
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
|
|
|||
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.20" />
|
||||
<option name="version" value="1.9.21" />
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/migrations.xml
generated
Normal file
10
.idea/migrations.xml
generated
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
A full developer contributors list can be found [here](https://github.com/vector-im/element-x-android/graphs/contributors).
|
||||
A full developer contributors list can be found [here](https://github.com/element-hq/element-x-android/graphs/contributors).
|
||||
|
||||
# Core team:
|
||||
|
||||
|
|
|
|||
208
CHANGES.md
208
CHANGES.md
|
|
@ -3,21 +3,21 @@ Changes in Element X v0.3.2 (2023-11-22)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- Add ongoing call indicator to rooms lists items. ([#1158](https://github.com/vector-im/element-x-android/issues/1158))
|
||||
- Add support for typing mentions in the message composer. ([#1453](https://github.com/vector-im/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/vector-im/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/vector-im/element-x-android/issues/1784))
|
||||
- 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 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))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Always ensure media temp dir exists ([#1790](https://github.com/vector-im/element-x-android/issues/1790))
|
||||
- Always ensure media temp dir exists ([#1790](https://github.com/element-hq/element-x-android/issues/1790))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Update icons and move away from `PreferenceText` components. ([#1718](https://github.com/vector-im/element-x-android/issues/1718))
|
||||
- Add item "This is the beginning of..." at the beginning of the timeline. ([#1801](https://github.com/vector-im/element-x-android/issues/1801))
|
||||
- LockScreen : rework LoggedInFlowNode and back management when locked. ([#1806](https://github.com/vector-im/element-x-android/issues/1806))
|
||||
- Suppress usage of removeTimeline method. ([#1824](https://github.com/vector-im/element-x-android/issues/1824))
|
||||
- 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))
|
||||
- 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))
|
||||
- Remove Element Call feature flag, it's now always enabled.
|
||||
- Reverted the EC base URL to `https://call.element.io`.
|
||||
- Moved the option to override this URL to developer settings from advanced settings.
|
||||
|
|
@ -28,16 +28,16 @@ Changes in Element X v0.3.1 (2023-11-09)
|
|||
|
||||
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/vector-im/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 🐛
|
||||
----------
|
||||
- Improve confusing text in the 'ready to start verification' screen. ([#879](https://github.com/vector-im/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/vector-im/element-x-android/issues/1560))
|
||||
- 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))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- PIN: Set lock grace period to 0. ([#1732](https://github.com/vector-im/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)
|
||||
|
|
@ -45,24 +45,24 @@ Changes in Element X v0.3.0 (2023-10-31)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- Element Call: change the 'join call' button in a chat room when there's an active call. ([#1158](https://github.com/vector-im/element-x-android/issues/1158))
|
||||
- Mentions: add mentions suggestion view in RTE ([#1452](https://github.com/vector-im/element-x-android/issues/1452))
|
||||
- Record and send voice messages ([#1596](https://github.com/vector-im/element-x-android/issues/1596))
|
||||
- Enable voice messages for all users ([#1669](https://github.com/vector-im/element-x-android/issues/1669))
|
||||
- Receive and play a voice message ([#2084](https://github.com/vector-im/element-x-android/issues/2084))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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.
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Group fallback notification to avoid having plenty of them displayed. ([#994](https://github.com/vector-im/element-x-android/issues/994))
|
||||
- Hide keyboard when exiting the chat room screen. ([#1375](https://github.com/vector-im/element-x-android/issues/1375))
|
||||
- Always register the pusher when application starts ([#1481](https://github.com/vector-im/element-x-android/issues/1481))
|
||||
- Ensure screen does not turn off when playing a video ([#1519](https://github.com/vector-im/element-x-android/issues/1519))
|
||||
- Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/vector-im/element-x-android/issues/1617))
|
||||
- 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))
|
||||
- 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))
|
||||
- Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/element-hq/element-x-android/issues/1617))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Remove usage of blocking methods. ([#1563](https://github.com/vector-im/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)
|
||||
|
|
@ -70,20 +70,20 @@ Changes in Element X v0.2.4 (2023-10-12)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- [Rich text editor] Add full screen mode ([#1447](https://github.com/vector-im/element-x-android/issues/1447))
|
||||
- Improve rendering of m.emote. ([#1497](https://github.com/vector-im/element-x-android/issues/1497))
|
||||
- Improve deleted session behavior. ([#1520](https://github.com/vector-im/element-x-android/issues/1520))
|
||||
- [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 deleted session behavior. ([#1520](https://github.com/element-hq/element-x-android/issues/1520))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- WebP images can't be sent as media. ([#1483](https://github.com/vector-im/element-x-android/issues/1483))
|
||||
- Fix back button not working in bottom sheets. ([#1517](https://github.com/vector-im/element-x-android/issues/1517))
|
||||
- Render body of unknown msgtype in the timeline and in the room list ([#1539](https://github.com/vector-im/element-x-android/issues/1539))
|
||||
- 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))
|
||||
- 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
|
||||
-------------
|
||||
- Room : makes subscribeToSync/unsubscribeFromSync suspendable. ([#1457](https://github.com/vector-im/element-x-android/issues/1457))
|
||||
- Add some Konsist tests. ([#1526](https://github.com/vector-im/element-x-android/issues/1526))
|
||||
- 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))
|
||||
|
||||
|
||||
Changes in Element X v0.2.3 (2023-09-27)
|
||||
|
|
@ -91,12 +91,12 @@ Changes in Element X v0.2.3 (2023-09-27)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- Handle installation of Apks from the media viewer. ([#1432](https://github.com/vector-im/element-x-android/pull/1432))
|
||||
- Integrate SDK 0.1.58 ([#1437](https://github.com/vector-im/element-x-android/pull/1437))
|
||||
- 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))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Element call: add custom parameters to Element Call urls. ([#1434](https://github.com/vector-im/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)
|
||||
|
|
@ -104,8 +104,8 @@ Changes in Element X v0.2.2 (2023-09-21)
|
|||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/vector-im/element-x-android/issues/1323))
|
||||
- Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/vector-im/element-x-android/issues/1395))
|
||||
- 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))
|
||||
|
||||
|
||||
Changes in Element X v0.2.1 (2023-09-20)
|
||||
|
|
@ -114,18 +114,18 @@ Changes in Element X v0.2.1 (2023-09-20)
|
|||
Features ✨
|
||||
----------
|
||||
- Bump Rust SDK to `v0.1.56`
|
||||
- [Rich text editor] Add link support to rich text editor ([#1309](https://github.com/vector-im/element-x-android/issues/1309))
|
||||
- Let the SDK figure the best scheme given an homeserver URL (thus allowing HTTP homeservers) ([#1382](https://github.com/vector-im/element-x-android/issues/1382))
|
||||
- [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))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Fix ANR on RoomList when notification settings change. ([#1370](https://github.com/vector-im/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
|
||||
-------------
|
||||
- Element Call: support scheme `io.element.call` ([#1377](https://github.com/vector-im/element-x-android/issues/1377))
|
||||
- [DI] Rework how dagger components are created and provided. ([#1378](https://github.com/vector-im/element-x-android/issues/1378))
|
||||
- Remove usage of async-uniffi as it leads to a deadlocks and memory leaks. ([#1381](https://github.com/vector-im/element-x-android/issues/1381))
|
||||
- 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))
|
||||
- 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)
|
||||
|
|
@ -134,37 +134,37 @@ Changes in Element X v0.2.0 (2023-09-18)
|
|||
Features ✨
|
||||
----------
|
||||
- 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/vector-im/element-x-android/issues/506))
|
||||
- Add a notification permission screen to the initial flow. ([#897](https://github.com/vector-im/element-x-android/issues/897))
|
||||
- Integrate Element Call into EX by embedding a call in a WebView. ([#1300](https://github.com/vector-im/element-x-android/issues/1300))
|
||||
- Implement Bloom effect modifier. ([#1217](https://github.com/vector-im/element-x-android/issues/1217))
|
||||
- Set color on display name and default avatar in the timeline. ([#1224](https://github.com/vector-im/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/vector-im/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/vector-im/element-x-android/issues/1172))
|
||||
- [Rich text editor] Add formatting menu (accessible via the '+' button) ([#1261](https://github.com/vector-im/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/vector-im/element-x-android/issues/1289))
|
||||
- [Rich text editor] Update design ([#1332](https://github.com/vector-im/element-x-android/issues/1332))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- [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 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))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Make links in room topic clickable ([#612](https://github.com/vector-im/element-x-android/issues/612))
|
||||
- Reply action: harmonize conditions in bottom sheet and swipe to reply. ([#1173](https://github.com/vector-im/element-x-android/issues/1173))
|
||||
- Fix system bar color after login on light theme. ([#1222](https://github.com/vector-im/element-x-android/issues/1222))
|
||||
- Fix long click on simple formatted messages ([#1232](https://github.com/vector-im/element-x-android/issues/1232))
|
||||
- Enable polls in release build. ([#1241](https://github.com/vector-im/element-x-android/issues/1241))
|
||||
- Fix top padding in room list when app is opened in offline mode. ([#1297](https://github.com/vector-im/element-x-android/issues/1297))
|
||||
- [Rich text editor] Fix 'text formatting' option only partially visible ([#1335](https://github.com/vector-im/element-x-android/issues/1335))
|
||||
- [Rich text editor] Ensure keyboard opens for reply and text formatting modes ([#1337](https://github.com/vector-im/element-x-android/issues/1337))
|
||||
- [Rich text editor] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/vector-im/element-x-android/issues/1347))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- [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] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/element-hq/element-x-android/issues/1347))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Add a sub-screen "Notifications" in the existing application Settings ([#510](https://github.com/vector-im/element-x-android/issues/510))
|
||||
- Exclude some groups related to analytics to be included. ([#1191](https://github.com/vector-im/element-x-android/issues/1191))
|
||||
- Use the new SyncIndicator API. ([#1244](https://github.com/vector-im/element-x-android/issues/1244))
|
||||
- Improve RoomSummary mapping by using RoomInfo. ([#1251](https://github.com/vector-im/element-x-android/issues/1251))
|
||||
- Ensure Posthog data are sent to "https://posthog.element.io" ([#1269](https://github.com/vector-im/element-x-android/issues/1269))
|
||||
- New app icon, with monochrome support. ([#1363](https://github.com/vector-im/element-x-android/issues/1363))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
|
||||
|
||||
Changes in Element X v0.1.6 (2023-09-04)
|
||||
|
|
@ -172,22 +172,22 @@ Changes in Element X v0.1.6 (2023-09-04)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- Enable the Polls feature. Allows to create, view, vote and end polls. ([#1196](https://github.com/vector-im/element-x-android/issues/1196))
|
||||
- Create poll. ([#1143](https://github.com/vector-im/element-x-android/issues/1143))
|
||||
- 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))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Ensure notification for Event from encrypted room get decrypted content. ([#1178](https://github.com/vector-im/element-x-android/issues/1178))
|
||||
- Make sure Snackbars are only displayed once. ([#928](https://github.com/vector-im/element-x-android/issues/928))
|
||||
- Fix the orientation of sent images. ([#1135](https://github.com/vector-im/element-x-android/issues/1135))
|
||||
- Bug reporter crashes when 'send logs' is disabled. ([#1168](https://github.com/vector-im/element-x-android/issues/1168))
|
||||
- Add missing link to the terms on the analytics setting screen. ([#1177](https://github.com/vector-im/element-x-android/issues/1177))
|
||||
- Re-enable `SyncService.withEncryptionSync` to improve decryption of notifications. ([#1198](https://github.com/vector-im/element-x-android/issues/1198))
|
||||
- Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/vector-im/element-x-android/issues/1995))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/element-hq/element-x-android/issues/1995))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Remove unnecessary year in copyright mention. ([#1187](https://github.com/vector-im/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)
|
||||
|
|
@ -195,7 +195,7 @@ Changes in Element X v0.1.5 (2023-08-28)
|
|||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Fix crash when opening any room. ([#1160](https://github.com/vector-im/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)
|
||||
|
|
@ -203,32 +203,32 @@ Changes in Element X v0.1.4 (2023-08-28)
|
|||
|
||||
Features ✨
|
||||
----------
|
||||
- Allow cancelling media upload ([#769](https://github.com/vector-im/element-x-android/issues/769))
|
||||
- Enable OIDC support. ([#1127](https://github.com/vector-im/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/vector-im/element-x-android/issues/1149))
|
||||
- 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))
|
||||
- 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 🐛
|
||||
----------
|
||||
- Videos sent from the app were cropped in some cases. ([#862](https://github.com/vector-im/element-x-android/issues/862))
|
||||
- Timeline: sender names are now displayed in one single line. ([#1033](https://github.com/vector-im/element-x-android/issues/1033))
|
||||
- Fix `TextButtons` being displayed in black. ([#1077](https://github.com/vector-im/element-x-android/issues/1077))
|
||||
- Linkify links in HTML contents. ([#1079](https://github.com/vector-im/element-x-android/issues/1079))
|
||||
- Fix bug reporter failing after not finding some log files. ([#1082](https://github.com/vector-im/element-x-android/issues/1082))
|
||||
- Fix rendering of inline elements in list items. ([#1090](https://github.com/vector-im/element-x-android/issues/1090))
|
||||
- Fix crash RuntimeException "No matching key found for the ciphertext in the stream" ([#1101](https://github.com/vector-im/element-x-android/issues/1101))
|
||||
- Make links in messages clickable again. ([#1111](https://github.com/vector-im/element-x-android/issues/1111))
|
||||
- When event has no id, just cancel parsing the latest room message for a room. ([#1125](https://github.com/vector-im/element-x-android/issues/1125))
|
||||
- Only display verification prompt after initial sync is done. ([#1131](https://github.com/vector-im/element-x-android/issues/1131))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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 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))
|
||||
- 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))
|
||||
|
||||
In development 🚧
|
||||
----------------
|
||||
- [Poll] Add feature flag in developer options ([#1064](https://github.com/vector-im/element-x-android/issues/1064))
|
||||
- [Polls] Improve UI and render ended state ([#1113](https://github.com/vector-im/element-x-android/issues/1113))
|
||||
- [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))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Compound: add `ListItem` and `ListSectionHeader` components. ([#990](https://github.com/vector-im/element-x-android/issues/990))
|
||||
- Migrate `object` to `data object` in sealed interface / class #1135 ([#1135](https://github.com/vector-im/element-x-android/issues/1135))
|
||||
- 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))
|
||||
|
||||
|
||||
Changes in Element X v0.1.2 (2023-08-16)
|
||||
|
|
@ -236,20 +236,20 @@ Changes in Element X v0.1.2 (2023-08-16)
|
|||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Filter push notifications using push rules. ([#640](https://github.com/vector-im/element-x-android/issues/640))
|
||||
- Use `for` instead of `forEach` in `DefaultDiffCacheInvalidator` to improve performance. ([#1035](https://github.com/vector-im/element-x-android/issues/1035))
|
||||
- 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))
|
||||
|
||||
In development 🚧
|
||||
----------------
|
||||
- [Poll] Render start event in the timeline ([#1031](https://github.com/vector-im/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
|
||||
-------------
|
||||
- Add Button component based on Compound designs ([#1021](https://github.com/vector-im/element-x-android/issues/1021))
|
||||
- Compound: implement dialogs. ([#1043](https://github.com/vector-im/element-x-android/issues/1043))
|
||||
- Compound: customise `IconButton` component. ([#1049](https://github.com/vector-im/element-x-android/issues/1049))
|
||||
- Compound: implement `DropdownMenu` customisations. ([#1050](https://github.com/vector-im/element-x-android/issues/1050))
|
||||
- Compound: implement Snackbar component. ([#1054](https://github.com/vector-im/element-x-android/issues/1054))
|
||||
- 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: 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 Snackbar component. ([#1054](https://github.com/element-hq/element-x-android/issues/1054))
|
||||
|
||||
|
||||
Changes in Element X v0.1.0 (2023-07-19)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
* @vector-im/element-x-android-reviewers
|
||||
* @element-hq/element-x-android-reviewers
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ internal fun PinIconPreview() = ElementPreview {
|
|||
}
|
||||
```
|
||||
|
||||
This will allow to preview the composable in both light and dark mode in Android Studio. This will also automatically add UI tests. The GitHub action [Record screenshots](https://github.com/vector-im/element-x-android/actions/workflows/recordScreenshots.yml) has to be run to record the new screenshots. The PR reviewer can trigger this for you if you're not part of the core team.
|
||||
This will allow to preview the composable in both light and dark mode in Android Studio. This will also automatically add UI tests. The GitHub action [Record screenshots](https://github.com/element-hq/element-x-android/actions/workflows/recordScreenshots.yml) has to be run to record the new screenshots. The PR reviewer can trigger this for you if you're not part of the core team.
|
||||
|
||||
### Authors
|
||||
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -1,4 +1,4 @@
|
|||
[](https://github.com/vector-im/element-x-android/actions/workflows/build.yml?query=branch%3Adevelop)
|
||||
[](https://github.com/element-hq/element-x-android/actions/workflows/build.yml?query=branch%3Adevelop)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
Element X Android is a [Matrix](https://matrix.org/) Android Client provided by [element.io](https://element.io/). This app is currently in a pre-alpha release stage with only basic functionalities.
|
||||
|
||||
The application is a total rewrite of [Element-Android](https://github.com/vector-im/element-android) using the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) underneath and targeting devices running Android 6+. The UI layer is written using [Jetpack Compose](https://developer.android.com/jetpack/compose), and the navigation is managed using [Appyx](https://github.com/bumble-tech/appyx).
|
||||
The application is a total rewrite of [Element-Android](https://github.com/element-hq/element-android) using the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) underneath and targeting devices running Android 6+. The UI layer is written using [Jetpack Compose](https://developer.android.com/jetpack/compose), and the navigation is managed using [Appyx](https://github.com/bumble-tech/appyx).
|
||||
|
||||
Learn more about why we are building Element X in our blog post: [https://element.io/blog/element-x-experience-the-future-of-element/](https://element.io/blog/element-x-experience-the-future-of-element/).
|
||||
|
||||
|
|
@ -58,11 +58,11 @@ We're doing this as a way to share code between platforms and while we've seen p
|
|||
|
||||
## Status
|
||||
|
||||
This project is in work in progress. The app does not cover yet all functionalities we expect. The list of supported features can be found in [this issue](https://github.com/vector-im/element-x-android/issues/911).
|
||||
This project is in work in progress. The app does not cover yet all functionalities we expect. The list of supported features can be found in [this issue](https://github.com/element-hq/element-x-android/issues/911).
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to get actively involved in the project? You're more than welcome! A good way to start is to check the issues that are labelled with the [good first issue](https://github.com/vector-im/element-x-android/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label. Let us know by commenting the issue that you're starting working on it.
|
||||
Want to get actively involved in the project? You're more than welcome! A good way to start is to check the issues that are labelled with the [good first issue](https://github.com/element-hq/element-x-android/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label. Let us know by commenting the issue that you're starting working on it.
|
||||
|
||||
But first make sure to read our [contribution guide](CONTRIBUTING.md) first.
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ Makes sure to select the `app` configuration when building (as we also have samp
|
|||
|
||||
## Support
|
||||
|
||||
When you are experiencing an issue on Element X Android, please first search in [GitHub issues](https://github.com/vector-im/element-x-android/issues)
|
||||
When you are experiencing an issue on Element X Android, please first search in [GitHub issues](https://github.com/element-hq/element-x-android/issues)
|
||||
and then in [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org).
|
||||
If after your research you still have a question, ask at [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting from the application settings. This is especially recommended when you encounter a crash.
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class TracingInitializer : Initializer<Unit> {
|
|||
)
|
||||
}
|
||||
bugReporter.cleanLogDirectoryIfNeeded()
|
||||
bugReporter.setCurrentTracingFilter(tracingConfiguration.filterConfiguration.filter)
|
||||
tracingService.setupTracing(tracingConfiguration)
|
||||
// Also set env variable for rust back trace
|
||||
Os.setenv("RUST_BACKTRACE", "1", true)
|
||||
|
|
|
|||
|
|
@ -33,13 +33,12 @@ import dagger.assisted.AssistedInject
|
|||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.appnav.di.SessionComponentFactory
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
|
||||
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +51,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
|||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
sessionComponentFactory: SessionComponentFactory,
|
||||
private val imageLoaderHolder: ImageLoaderHolder,
|
||||
) : ParentNode<LoggedInAppScopeFlowNode.NavTarget>(
|
||||
navModel = PermanentNavModel(
|
||||
navTargets = setOf(NavTarget),
|
||||
|
|
@ -78,8 +78,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
|||
super.onBuilt()
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
val imageLoaderFactory = bindings<MatrixUIBindings>().loggedInImageLoaderFactory()
|
||||
Coil.setImageLoader(imageLoaderFactory)
|
||||
Coil.setImageLoader(imageLoaderHolder.get(inputs.matrixClient))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,6 +256,10 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
}
|
||||
is NavTarget.Room -> {
|
||||
val callback = object : RoomLoadedFlowNode.Callback {
|
||||
override fun onOpenRoom(roomId: RoomId) {
|
||||
backstack.push(NavTarget.Room(roomId))
|
||||
}
|
||||
|
||||
override fun onForwardedToSingleRoom(roomId: RoomId) {
|
||||
coroutineScope.launch { attachRoom(roomId) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ class IntentResolver @Inject constructor(
|
|||
private val oidcIntentResolver: OidcIntentResolver
|
||||
) {
|
||||
fun resolve(intent: Intent): ResolvedIntent? {
|
||||
if (intent.canBeIgnored()) return null
|
||||
|
||||
val deepLinkData = deeplinkParser.getFromIntent(intent)
|
||||
if (deepLinkData != null) return ResolvedIntent.Navigation(deepLinkData)
|
||||
|
||||
|
|
@ -45,3 +47,8 @@ class IntentResolver @Inject constructor(
|
|||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun Intent.canBeIgnored(): Boolean {
|
||||
return action == Intent.ACTION_MAIN &&
|
||||
categories?.contains(Intent.CATEGORY_LAUNCHER) == true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
|||
), DaggerComponentOwner {
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onOpenRoom(roomId: RoomId)
|
||||
fun onForwardedToSingleRoom(roomId: RoomId)
|
||||
fun onOpenGlobalNotificationSettings()
|
||||
}
|
||||
|
|
@ -134,6 +135,10 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
|||
override fun onOpenGlobalNotificationSettings() {
|
||||
callbacks.forEach { it.onOpenGlobalNotificationSettings() }
|
||||
}
|
||||
|
||||
override fun onOpenRoom(roomId: RoomId) {
|
||||
callbacks.forEach { it.onOpenRoom(roomId) }
|
||||
}
|
||||
}
|
||||
return roomDetailsEntryPoint.nodeBuilder(this, buildContext)
|
||||
.params(RoomDetailsEntryPoint.Params(initialTarget))
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import com.bumble.appyx.core.plugin.Plugin
|
|||
import com.bumble.appyx.navmodel.backstack.activeElement
|
||||
import com.bumble.appyx.testing.junit4.util.MainDispatcherRule
|
||||
import com.bumble.appyx.testing.unit.common.helper.parentNodeTestHelper
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.appnav.di.RoomComponentFactory
|
||||
import io.element.android.appnav.room.RoomLoadedFlowNode
|
||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||
|
|
@ -83,7 +83,7 @@ class RoomFlowNodeTest {
|
|||
}
|
||||
|
||||
override fun build(): Node {
|
||||
return node(buildContext) {}.also {
|
||||
return node(buildContext) {}.also {
|
||||
nodeId = it.id
|
||||
}
|
||||
}
|
||||
|
|
@ -122,10 +122,10 @@ class RoomFlowNodeTest {
|
|||
val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper()
|
||||
|
||||
// THEN
|
||||
Truth.assertThat(roomFlowNode.backstack.activeElement).isEqualTo(RoomLoadedFlowNode.NavTarget.Messages)
|
||||
assertThat(roomFlowNode.backstack.activeElement).isEqualTo(RoomLoadedFlowNode.NavTarget.Messages)
|
||||
roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.Messages, Lifecycle.State.CREATED)
|
||||
val messagesNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.Messages)!!
|
||||
Truth.assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId)
|
||||
assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -147,6 +147,6 @@ class RoomFlowNodeTest {
|
|||
// THEN
|
||||
roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED)
|
||||
val roomDetailsNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.RoomDetails)!!
|
||||
Truth.assertThat(roomDetailsNode.id).isEqualTo(fakeRoomDetailsEntryPoint.nodeId)
|
||||
assertThat(roomDetailsNode.id).isEqualTo(fakeRoomDetailsEntryPoint.nodeId)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,17 @@ import org.robolectric.RuntimeEnvironment
|
|||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class IntentResolverTest {
|
||||
@Test
|
||||
fun `resolve launcher intent should return null`() {
|
||||
val sut = createIntentResolver()
|
||||
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
|
||||
action = Intent.ACTION_MAIN
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
val result = sut.resolve(intent)
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test resolve navigation intent root`() {
|
||||
val sut = createIntentResolver()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.appnav.room
|
||||
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
|
|
@ -39,8 +39,8 @@ class LoadingRoomStateFlowFactoryTest {
|
|||
flowFactory
|
||||
.create(this, A_ROOM_ID)
|
||||
.test {
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,10 +53,10 @@ class LoadingRoomStateFlowFactoryTest {
|
|||
flowFactory
|
||||
.create(this, A_ROOM_ID)
|
||||
.test {
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
matrixClient.givenGetRoomResult(A_ROOM_ID, room)
|
||||
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,12 +68,9 @@ class LoadingRoomStateFlowFactoryTest {
|
|||
flowFactory
|
||||
.create(this, A_ROOM_ID)
|
||||
.test {
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
|
||||
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
|
||||
Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Error)
|
||||
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ allprojects {
|
|||
config.from(files("$rootDir/tools/detekt/detekt.yml"))
|
||||
}
|
||||
dependencies {
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.3.3")
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.3.5")
|
||||
}
|
||||
|
||||
// KtLint
|
||||
|
|
@ -130,10 +130,10 @@ sonar {
|
|||
property("sonar.host.url", "https://sonarcloud.io")
|
||||
property("sonar.projectVersion", "1.0") // TODO project(":app").android.defaultConfig.versionName)
|
||||
property("sonar.sourceEncoding", "UTF-8")
|
||||
property("sonar.links.homepage", "https://github.com/vector-im/element-x-android/")
|
||||
property("sonar.links.ci", "https://github.com/vector-im/element-x-android/actions")
|
||||
property("sonar.links.scm", "https://github.com/vector-im/element-x-android/")
|
||||
property("sonar.links.issue", "https://github.com/vector-im/element-x-android/issues")
|
||||
property("sonar.links.homepage", "https://github.com/element-hq/element-x-android/")
|
||||
property("sonar.links.ci", "https://github.com/element-hq/element-x-android/actions")
|
||||
property("sonar.links.scm", "https://github.com/element-hq/element-x-android/")
|
||||
property("sonar.links.issue", "https://github.com/element-hq/element-x-android/issues")
|
||||
property("sonar.organization", "new_vector_ltd_organization")
|
||||
property("sonar.login", if (project.hasProperty("SONAR_LOGIN")) project.property("SONAR_LOGIN")!! else "invalid")
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/vector-im/compound-android).
|
||||
Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/element-hq/compound-android).
|
||||
|
|
|
|||
1
changelog.d/1944.misc
Normal file
1
changelog.d/1944.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add toggle in the notification settings to disable notifications for room invites.
|
||||
1
changelog.d/1950.bugfix
Normal file
1
changelog.d/1950.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fix rendering of user name with vertical text by clipping the text.
|
||||
1
changelog.d/1965.misc
Normal file
1
changelog.d/1965.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Update rendering of Emojis displayed during verification.
|
||||
1
changelog.d/1979.misc
Normal file
1
changelog.d/1979.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Hide sender info in direct rooms
|
||||
1
changelog.d/1991.bugfix
Normal file
1
changelog.d/1991.bugfix
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fix avatar not displayed in notification when the app is not in background
|
||||
1
changelog.d/1991.misc
Normal file
1
changelog.d/1991.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Render images in Notification
|
||||
|
|
@ -117,7 +117,7 @@ You can also have access to the aars through the [release](https://github.com/ma
|
|||
|
||||
#### Build the SDK locally
|
||||
|
||||
Easiest way: run the script [./tools/sdk/build_rust_sdk.sh](./tools/sdk/build_rust_sdk.sh) and just answer the questions.
|
||||
Easiest way: run the script [../tools/sdk/build_rust_sdk.sh](../tools/sdk/build_rust_sdk.sh) and just answer the questions.
|
||||
|
||||
Legacy way:
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ We are using [Gradle version catalog](https://docs.gradle.org/current/userguide/
|
|||
All the dependencies (including android artifact, gradle plugin, etc.) should be declared in [../gradle/libs.versions.toml](libs.versions.toml) file.
|
||||
Some dependency, mainly because they are not shared can be declared in `build.gradle.kts` files.
|
||||
|
||||
[Renovate](https://github.com/apps/renovate) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one. A [dependency dashboard issue](https://github.com/vector-im/element-x-android/issues/150) is maintained by the tool and allow to perform some actions.
|
||||
[Renovate](https://github.com/apps/renovate) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one. A [dependency dashboard issue](https://github.com/element-hq/element-x-android/issues/150) is maintained by the tool and allow to perform some actions.
|
||||
|
||||
### Test
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ bundle exec danger pr <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
|||
For instance:
|
||||
|
||||
```shell
|
||||
bundle exec danger pr https://github.com/vector-im/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
|
||||
bundle exec danger pr https://github.com/element-hq/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
|
||||
```
|
||||
|
||||
We may need to create a GitHub token to have less API rate limiting, and then set the env var:
|
||||
|
|
@ -84,7 +84,7 @@ bundle exec danger-kotlin pr <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
|||
To let Danger check all the PRs, including PRs form forks, a GitHub account have been created:
|
||||
- login: ElementBot
|
||||
- password: Stored on Passbolt
|
||||
- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
|
||||
- GitHub token: A token with limited access has been created and added to the repository https://github.com/element-hq/element-x-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
|
||||
|
||||
PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@
|
|||
1) Disable "Use Android Studio HTTP proxy settings" and pick "Manual proxy configuration".
|
||||
1) Set `127.0.0.1` as "Host name" and `8080` as "Port number".
|
||||
1) Click "Apply" and verify that "Proxy status" is "Success" and close the settings window.
|
||||
<img width="932" alt="Screenshot 2023-10-04 at 14 48 47" src="https://github.com/vector-im/element-x-android/assets/1273124/bf99a053-20b0-42a4-91d3-9602f709f684">
|
||||
<img width="932" alt="Screenshot 2023-10-04 at 14 48 47" src="https://github.com/element-hq/element-x-android/assets/1273124/bf99a053-20b0-42a4-91d3-9602f709f684">
|
||||
1) Install the mitmproxy CA cert (this is needed to see traffic from java/kotlin code, it's not needed for traffic coming from native code e.g. the matrix-rust-sdk).
|
||||
1) Open the emulator Chrome browser app
|
||||
1) Go to the url `mitm.it`
|
||||
1) Follow the instructions to install the CA cert on Android devices.
|
||||
<img width="606" alt="Screenshot 2023-10-04 at 14 51 27" src="https://github.com/vector-im/element-x-android/assets/1273124/5f2b6f27-6958-4ea7-97fe-c7f06d105da5">
|
||||
<img width="606" alt="Screenshot 2023-10-04 at 14 51 27" src="https://github.com/element-hq/element-x-android/assets/1273124/5f2b6f27-6958-4ea7-97fe-c7f06d105da5">
|
||||
1) Slightly modify the Element X app source code.
|
||||
1) Go to the `RustMatrixClientFactory.create()` method.
|
||||
1) Add `.disableSslVerification()` in the `ClientBuilder` method chain.
|
||||
1) Build and run the Element X app.
|
||||
1) Enjoy, you will see all the traffic in mitmproxy's web interface.
|
||||
<img width="1110" alt="Screenshot 2023-10-04 at 14 50 03" src="https://github.com/vector-im/element-x-android/assets/1273124/5d039efd-448d-426c-a384-dbbceb9f33ac">
|
||||
<img width="1110" alt="Screenshot 2023-10-04 at 14 50 03" src="https://github.com/element-hq/element-x-android/assets/1273124/5d039efd-448d-426c-a384-dbbceb9f33ac">
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ A comprehensive [color definition documentation](https://compound.element.io/?pa
|
|||
Most icons should be available as part of the [Compound icon library](https://compound.element.io/?path=/docs/tokens-icons--docs)
|
||||
|
||||
All drawable are auto-generated as part of the design tokens library. You can find
|
||||
all assets in [`vector-im/compound-design-tokens#assets/android`](https://github.com/vector-im/compound-design-tokens/tree/develop/assets/android)
|
||||
all assets in [`element-hq/compound-design-tokens#assets/android`](https://github.com/element-hq/compound-design-tokens/tree/main/assets/android)
|
||||
|
||||
If you are missing an icon, follow to [contribution guidelines for icons](https://www.figma.com/file/gkNXqPoiJhEv2wt0EJpew4/Compound-Icons?type=design&node-id=178-3119&t=j2uSJD9xPXJn5aRM-0)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ The easiest way to do that is to use the debug signature that is shared between
|
|||
|
||||
You can clone the project by running:
|
||||
```bash
|
||||
git clone git@github.com:vector-im/element-x-android.git
|
||||
git clone git@github.com:element-hq/element-x-android.git
|
||||
```
|
||||
or
|
||||
```bash
|
||||
git clone https://github.com/vector-im/element-x-android.git
|
||||
git clone https://github.com/element-hq/element-x-android.git
|
||||
```
|
||||
|
||||
You will also need to install [bundletool](https://developer.android.com/studio/command-line/bundletool). On MacOS, you can run the following command:
|
||||
|
|
@ -33,7 +33,7 @@ brew install bundletool
|
|||
|
||||
## Steps
|
||||
|
||||
1. Open the GitHub release that you want to install from https://github.com/vector-im/element-x-android/releases
|
||||
1. Open the GitHub release that you want to install from https://github.com/element-hq/element-x-android/releases
|
||||
2. Download the asset `app-release-signed.aab`
|
||||
3. Navigate to the folder where you cloned the project and run the following command:
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
This file contains some rough notes about Oidc implementation, with some examples of actual data.
|
||||
|
||||
[ios implementation](https://github.com/vector-im/element-x-ios/compare/develop...doug/oidc-temp)
|
||||
[ios implementation](https://github.com/element-hq/element-x-ios/compare/develop...doug/oidc-temp)
|
||||
|
||||
Rust sdk branch: https://github.com/matrix-org/matrix-rust-sdk/tree/oidc-ffi
|
||||
|
||||
Figma https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?node-id=133-5426&t=yQXKeANatk6keoZF-0
|
||||
|
||||
Server list: https://github.com/vector-im/oidc-playground
|
||||
Server list: https://github.com/element-hq/oidc-playground
|
||||
|
||||
Metadata iOS: (from https://github.com/vector-im/element-x-ios/blob/5f9d07377cebc4f21d9668b1a25f6e3bb22f64a1/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift#L28)
|
||||
Metadata iOS: (from https://github.com/element-hq/element-x-ios/blob/5f9d07377cebc4f21d9668b1a25f6e3bb22f64a1/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift#L28)
|
||||
|
||||
clientName: InfoPlistReader.main.bundleDisplayName,
|
||||
redirectUri: "io.element:/callback",
|
||||
|
|
|
|||
|
|
@ -86,13 +86,13 @@ Exceptions can occur:
|
|||
We use automatic assignment for PR reviews. **A PR is automatically routed by GitHub to one team member** using the round robin algorithm. Additional reviewers can be used for complex changes or when the first reviewer is not confident enough on the changes.
|
||||
The process is the following:
|
||||
|
||||
- The PR creator selects the [element-x-android-reviewers](https://github.com/orgs/vector-im/teams/element-x-android-reviewers) team as a reviewer.
|
||||
- The PR creator selects the [element-x-android-reviewers](https://github.com/orgs/element-hq/teams/element-x-android-reviewers) team as a reviewer.
|
||||
- GitHub automatically assign the reviewer. If the reviewer is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
|
||||
- Alternatively, the PR creator can directly assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at their PR.
|
||||
- Reviewers get a notification to make the review: they review the code following the good practice (see the rest of this document).
|
||||
- After making their own review, if they feel not confident enough, they can ask another person for a full review, or they can tag someone within a PR comment to check specific lines.
|
||||
|
||||
For PRs coming from the community, the issue wrangler can assign either the team [element-x-android-reviewers](https://github.com/orgs/vector-im/teams/element-x-android-reviewers) or any member directly.
|
||||
For PRs coming from the community, the issue wrangler can assign either the team [element-x-android-reviewers](https://github.com/orgs/element-hq/teams/element-x-android-reviewers) or any member directly.
|
||||
|
||||
##### PR review time
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ If installed correctly, `git push` and `git pull` will now include LFS content.
|
|||
|
||||
## Recording
|
||||
|
||||
Recording of screenshots is done by triggering the GitHub action [Record screenshots](https://github.com/vector-im/element-x-android/actions/workflows/recordScreenshots.yml), to avoid differences of generated binary files (png images) depending on developers' environment.
|
||||
Recording of screenshots is done by triggering the GitHub action [Record screenshots](https://github.com/element-hq/element-x-android/actions/workflows/recordScreenshots.yml), to avoid differences of generated binary files (png images) depending on developers' environment.
|
||||
|
||||
So basically, you will create a branch, do some commits with your work on it, then push your branch, trigger the GitHub action to record the screenshots (only if you think preview may have changed), and finally create a pull request. The GitHub action will record the screenshots and commit the changes to the branch.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
First release of Element X 🚀!
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bug fixes and add OIDC support.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bug fixes and add OIDC support.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bugfixes.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: Element Call, design update, bugfixes
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: Element Call, design update, bugfixes
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bugfixes
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bugfixes.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: bugfixes.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: Element Call, voice message.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
Main changes in this version: Mainly bug fixes.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
Full changelog: https://github.com/element-hq/element-x-android/releases
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ Main changes in this version:
|
|||
- Adding mentions to a message is now possible, but it's disabled by default as it's a work in progress. They can be enabled in the developer options.
|
||||
- Voice messages behavior changed: there is no need to keep pressing to record, to start recording a message just tap on the mic button, then tap again to stop recording.
|
||||
- Added a marker in the timeline to indicate the starting point of the room messages.
|
||||
Full changelog: https://github.com/vector-im/element-x-android/releases
|
||||
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_share_data">"Elemzési adatok megosztása"</string>
|
||||
<string name="screen_analytics_settings_help_us_improve">"Anonim használati adatok megosztása a problémák azonosítása érdekében."</string>
|
||||
<string name="screen_analytics_settings_read_terms">"%1$s olvashatja el a feltételeinket."</string>
|
||||
<string name="screen_analytics_settings_read_terms_content_link">"Itt"</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_share_data">"Bagikan data analitik"</string>
|
||||
<string name="screen_analytics_settings_help_us_improve">"Bagikan data penggunaan anonim untuk membantu kami mengidentifikasi masalah."</string>
|
||||
<string name="screen_analytics_settings_read_terms">"Anda dapat membaca semua persyaratan kami %1$s."</string>
|
||||
<string name="screen_analytics_settings_read_terms_content_link">"di sini"</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">"Nem rögzítünk vagy profilozunk személyes adatokat"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Anonim használati adatok megosztása a problémák azonosítása érdekében."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"%1$s olvashatja el a feltételeinket."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"Itt"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Ezt bármikor kikapcsolhatja"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"Adatait nem osztjuk meg harmadik felekkel"</string>
|
||||
<string name="screen_analytics_prompt_title">"Segítsen az %1$s fejlesztésében"</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">"Kami tidak akan merekam atau memprofil data pribadi apa pun"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Bagikan data penggunaan anonim untuk membantu kami mengidentifikasi masalah."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Anda dapat membaca semua persyaratan kami %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"di sini"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Anda dapat mematikan ini kapan saja"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"Kami tidak akan membagikan data Anda dengan pihak ketiga"</string>
|
||||
<string name="screen_analytics_prompt_title">"Bantu sempurnakan %1$s"</string>
|
||||
</resources>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package io.element.android.features.cachecleaner.impl
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -46,9 +46,9 @@ class DefaultCacheCleanerTest {
|
|||
// Check the files are gone but the sub dirs are not.
|
||||
DefaultCacheCleaner.SUBDIRS_TO_CLEANUP.forEach {
|
||||
File(temporaryFolder.root, it).apply {
|
||||
Truth.assertThat(exists()).isTrue()
|
||||
Truth.assertThat(isDirectory).isTrue()
|
||||
Truth.assertThat(listFiles()).isEmpty()
|
||||
assertThat(exists()).isTrue()
|
||||
assertThat(isDirectory).isTrue()
|
||||
assertThat(listFiles()).isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
features/call/src/main/res/values-hu/translations.xml
Normal file
6
features/call/src/main/res/values-hu/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">"Folyamatban lévő hívás"</string>
|
||||
<string name="call_foreground_service_message_android">"Koppintson a híváshoz való visszatéréshez"</string>
|
||||
<string name="call_foreground_service_title_android">"☎️ Hívás folyamatban"</string>
|
||||
</resources>
|
||||
6
features/call/src/main/res/values-in/translations.xml
Normal file
6
features/call/src/main/res/values-in/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">"Panggilan berlangsung"</string>
|
||||
<string name="call_foreground_service_message_android">"Ketuk untuk kembali ke panggilan"</string>
|
||||
<string name="call_foreground_service_title_android">"☎️ Panggilan sedang berlangsung"</string>
|
||||
</resources>
|
||||
|
|
@ -39,7 +39,6 @@ class MapWebkitPermissionsTest {
|
|||
@Test
|
||||
fun `given any other permission, it returns nothing`() {
|
||||
val permission = mapWebkitPermissions(arrayOf(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID))
|
||||
assertThat(permission).isEqualTo(emptyList<String>())
|
||||
assertThat(permission).isEmpty()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.api
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
||||
interface StartDMAction {
|
||||
/**
|
||||
* Try to find an existing DM with the given user, or create one if none exists.
|
||||
* @param userId The user to start a DM with.
|
||||
* @param actionState The state to update with the result of the action.
|
||||
*/
|
||||
suspend fun execute(userId: UserId, actionState: MutableState<Async<RoomId>>)
|
||||
}
|
||||
|
|
@ -67,6 +67,7 @@ dependencies {
|
|||
testImplementation(projects.libraries.mediaupload.test)
|
||||
testImplementation(projects.libraries.permissions.test)
|
||||
testImplementation(projects.libraries.usersearch.test)
|
||||
testImplementation(projects.features.createroom.test)
|
||||
testImplementation(projects.tests.testutils)
|
||||
|
||||
ksp(libs.showkase.processor)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.impl
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.StartDMResult
|
||||
import io.element.android.libraries.matrix.api.room.startDM
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import javax.inject.Inject
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultStartDMAction @Inject constructor(
|
||||
private val matrixClient: MatrixClient,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : StartDMAction {
|
||||
|
||||
override suspend fun execute(userId: UserId, actionState: MutableState<Async<RoomId>>) {
|
||||
actionState.value = Async.Loading()
|
||||
when (val result = matrixClient.startDM(userId)) {
|
||||
is StartDMResult.Success -> {
|
||||
if (result.isNew) {
|
||||
analyticsService.capture(CreatedRoom(isDM = true))
|
||||
}
|
||||
actionState.value = Async.Success(result.roomId)
|
||||
}
|
||||
is StartDMResult.Failure -> {
|
||||
actionState.value = Async.Failure(result.throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,21 +21,16 @@ import androidx.compose.runtime.MutableState
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.features.createroom.impl.userlist.SelectionMode
|
||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
||||
import io.element.android.features.createroom.impl.userlist.UserListPresenter
|
||||
import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.usersearch.api.UserRepository
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -43,8 +38,7 @@ class CreateRoomRootPresenter @Inject constructor(
|
|||
presenterFactory: UserListPresenter.Factory,
|
||||
userRepository: UserRepository,
|
||||
userListDataStore: UserListDataStore,
|
||||
private val matrixClient: MatrixClient,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val startDMAction: StartDMAction,
|
||||
private val buildMeta: BuildMeta,
|
||||
) : Presenter<CreateRoomRootState> {
|
||||
|
||||
|
|
@ -61,37 +55,22 @@ class CreateRoomRootPresenter @Inject constructor(
|
|||
val userListState = presenter.present()
|
||||
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
val startDmAction: MutableState<Async<RoomId>> = remember { mutableStateOf(Async.Uninitialized) }
|
||||
val startDmActionState: MutableState<Async<RoomId>> = remember { mutableStateOf(Async.Uninitialized) }
|
||||
|
||||
fun handleEvents(event: CreateRoomRootEvents) {
|
||||
when (event) {
|
||||
is CreateRoomRootEvents.StartDM -> localCoroutineScope.startDm(event.matrixUser, startDmAction)
|
||||
CreateRoomRootEvents.CancelStartDM -> startDmAction.value = Async.Uninitialized
|
||||
is CreateRoomRootEvents.StartDM -> localCoroutineScope.launch {
|
||||
startDMAction.execute(event.matrixUser.userId, startDmActionState)
|
||||
}
|
||||
CreateRoomRootEvents.CancelStartDM -> startDmActionState.value = Async.Uninitialized
|
||||
}
|
||||
}
|
||||
|
||||
return CreateRoomRootState(
|
||||
applicationName = buildMeta.applicationName,
|
||||
userListState = userListState,
|
||||
startDmAction = startDmAction.value,
|
||||
startDmAction = startDmActionState.value,
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.startDm(matrixUser: MatrixUser, startDmAction: MutableState<Async<RoomId>>) = launch {
|
||||
suspend {
|
||||
matrixClient.findDM(matrixUser.userId).use { existingDM ->
|
||||
existingDM?.roomId ?: createDM(matrixUser)
|
||||
}
|
||||
}.runCatchingUpdatingState(startDmAction)
|
||||
}
|
||||
|
||||
private suspend fun createDM(user: MatrixUser): RoomId {
|
||||
return matrixClient
|
||||
.createDM(user.userId)
|
||||
.onSuccess {
|
||||
analyticsService.capture(CreatedRoom(isDM = true))
|
||||
}
|
||||
.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<?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">"Új szoba"</string>
|
||||
<string name="screen_create_room_action_invite_people">"Hívja meg ismerőseit az Elementbe"</string>
|
||||
<string name="screen_create_room_add_people_title">"Emberek meghívása"</string>
|
||||
<string name="screen_create_room_error_creating_room">"Hiba történt a szoba létrehozásakor"</string>
|
||||
<string name="screen_create_room_private_option_description">"A szobában lévő üzenetek titkosítottak. A titkosítást utólag nem lehet kikapcsolni."</string>
|
||||
<string name="screen_create_room_private_option_title">"Privát szoba (csak meghívással)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Az üzenetek nincsenek titkosítva, és bárki elolvashatja őket. A titkosítást később is engedélyezheti."</string>
|
||||
<string name="screen_create_room_public_option_title">"Nyilvános szoba (bárki)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Szoba neve"</string>
|
||||
<string name="screen_create_room_topic_label">"Téma (nem kötelező)"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Hiba történt a csevegés indításakor"</string>
|
||||
<string name="screen_create_room_title">"Szoba létrehozása"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?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">"Ruangan baru"</string>
|
||||
<string name="screen_create_room_action_invite_people">"Undang teman ke Element"</string>
|
||||
<string name="screen_create_room_add_people_title">"Undang seseorang"</string>
|
||||
<string name="screen_create_room_error_creating_room">"Terjadi kesalahan saat membuat ruangan"</string>
|
||||
<string name="screen_create_room_private_option_description">"Pesan di ruangan ini dienkripsi. Enkripsi tidak dapat dinonaktifkan setelahnya."</string>
|
||||
<string name="screen_create_room_private_option_title">"Ruangan pribadi (hanya undangan)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Pesan tidak dienkripsi dan siapa pun dapat membacanya. Anda dapat mengaktifkan enkripsi di kemudian hari."</string>
|
||||
<string name="screen_create_room_public_option_title">"Ruang publik (siapa saja)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Nama ruangan"</string>
|
||||
<string name="screen_create_room_topic_label">"Topik (opsional)"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Terjadi kesalahan saat mencoba memulai obrolan"</string>
|
||||
<string name="screen_create_room_title">"Buat ruangan"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.impl
|
||||
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultStartDMActionTests {
|
||||
|
||||
@Test
|
||||
fun `when dm is found, assert state is updated with given room id`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(A_ROOM_ID)
|
||||
}
|
||||
val action = createStartDMAction(matrixClient)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when dm is not found, assert dm is created, state is updated with given room id and analytics get called`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(null)
|
||||
givenCreateDmResult(Result.success(A_ROOM_ID))
|
||||
}
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val action = createStartDMAction(matrixClient, analyticsService)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
assertThat(analyticsService.capturedEvents).containsExactly(CreatedRoom(isDM = true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when dm creation fails, assert state is updated with given error`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(null)
|
||||
givenCreateDmResult(Result.failure(A_THROWABLE))
|
||||
}
|
||||
val action = createStartDMAction(matrixClient)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Failure<RoomId>(A_THROWABLE))
|
||||
}
|
||||
|
||||
private fun createStartDMAction(
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||
): DefaultStartDMAction {
|
||||
return DefaultStartDMAction(
|
||||
matrixClient = matrixClient,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,25 +20,21 @@ import app.cash.molecule.RecompositionMode
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenter
|
||||
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory
|
||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
||||
import io.element.android.features.createroom.impl.userlist.aUserListState
|
||||
import io.element.android.features.createroom.test.FakeStartDMAction
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -47,142 +43,57 @@ class CreateRoomRootPresenterTests {
|
|||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
|
||||
private lateinit var userRepository: FakeUserRepository
|
||||
private lateinit var presenter: CreateRoomRootPresenter
|
||||
private lateinit var fakeUserListPresenter: FakeUserListPresenter
|
||||
private lateinit var fakeMatrixClient: FakeMatrixClient
|
||||
private lateinit var fakeAnalyticsService: FakeAnalyticsService
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
fakeUserListPresenter = FakeUserListPresenter()
|
||||
fakeMatrixClient = FakeMatrixClient()
|
||||
fakeAnalyticsService = FakeAnalyticsService()
|
||||
userRepository = FakeUserRepository()
|
||||
presenter = CreateRoomRootPresenter(
|
||||
presenterFactory = FakeUserListPresenterFactory(fakeUserListPresenter),
|
||||
userRepository = userRepository,
|
||||
userListDataStore = UserListDataStore(),
|
||||
matrixClient = fakeMatrixClient,
|
||||
analyticsService = fakeAnalyticsService,
|
||||
buildMeta = aBuildMeta(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
fun `present - start DM action complete scenario`() = runTest {
|
||||
val startDMAction = FakeStartDMAction()
|
||||
val presenter = createCreateRoomRootPresenter(startDMAction)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
|
||||
assertThat(initialState.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
|
||||
assertThat(initialState.applicationName).isEqualTo(aBuildMeta().applicationName)
|
||||
assertThat(initialState.userListState.selectedUsers).isEmpty()
|
||||
assertThat(initialState.userListState.isSearchActive).isFalse()
|
||||
assertThat(initialState.userListState.isMultiSelectionEnabled).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger create DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - creating a DM records analytics event`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
skipItems(2)
|
||||
|
||||
val analyticsEvent = fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>().firstOrNull()
|
||||
assertThat(analyticsEvent).isNotNull()
|
||||
assertThat(analyticsEvent?.isDM).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger retrieve DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val fakeDmResult = FakeMatrixRoom(roomId = RoomId("!fakeDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(fakeDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(fakeDmResult.roomId)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger retry create DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
fakeUserListPresenter.givenState(aUserListState().copy(selectedUsers = persistentListOf(matrixUser)))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmError(A_THROWABLE)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
val startDMSuccessResult = Async.Success(A_ROOM_ID)
|
||||
val startDMFailureResult = Async.Failure<RoomId>(A_THROWABLE)
|
||||
|
||||
// Failure
|
||||
startDMAction.givenExecuteResult(startDMFailureResult)
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Failure::class.java)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(startDMFailureResult)
|
||||
state.eventSink(CreateRoomRootEvents.CancelStartDM)
|
||||
}
|
||||
|
||||
// Cancel
|
||||
stateAfterStartDM.eventSink(CreateRoomRootEvents.CancelStartDM)
|
||||
val stateAfterCancel = awaitItem()
|
||||
assertThat(stateAfterCancel.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
|
||||
|
||||
// Failure
|
||||
stateAfterCancel.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
// Success
|
||||
startDMAction.givenExecuteResult(startDMSuccessResult)
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(Async.Uninitialized)
|
||||
state.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
}
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterSecondAttempt = awaitItem()
|
||||
assertThat(stateAfterSecondAttempt.startDmAction).isInstanceOf(Async.Failure::class.java)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(startDMSuccessResult)
|
||||
}
|
||||
|
||||
// Retry with success
|
||||
fakeMatrixClient.givenCreateDmError(null)
|
||||
stateAfterSecondAttempt.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterRetryStartDM = awaitItem()
|
||||
assertThat(stateAfterRetryStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterRetryStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCreateRoomRootPresenter(
|
||||
startDMAction: StartDMAction = FakeStartDMAction(),
|
||||
): CreateRoomRootPresenter {
|
||||
return CreateRoomRootPresenter(
|
||||
presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()),
|
||||
userRepository = FakeUserRepository(),
|
||||
userListDataStore = UserListDataStore(),
|
||||
startDMAction = startDMAction,
|
||||
buildMeta = aBuildMeta(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
features/createroom/test/build.gradle.kts
Normal file
31
features/createroom/test/build.gradle.kts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("io.element.android-compose-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.features.createroom.test"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.coroutines.core)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.matrix.test)
|
||||
implementation(projects.libraries.architecture)
|
||||
api(projects.features.createroom.api)
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.test
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
class FakeStartDMAction : StartDMAction {
|
||||
|
||||
private var executeResult: Async<RoomId> = Async.Success(A_ROOM_ID)
|
||||
|
||||
fun givenExecuteResult(result: Async<RoomId>) {
|
||||
executeResult = result
|
||||
}
|
||||
|
||||
override suspend fun execute(userId: UserId, actionState: MutableState<Async<RoomId>>) {
|
||||
actionState.value = Async.Loading()
|
||||
delay(1)
|
||||
actionState.value = executeResult
|
||||
}
|
||||
}
|
||||
13
features/ftue/impl/src/main/res/values-hu/translations.xml
Normal file
13
features/ftue/impl/src/main/res/values-hu/translations.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_migration_message">"Ez egy egyszeri folyamat, köszönjük a türelmét."</string>
|
||||
<string name="screen_migration_title">"A fiók beállítása."</string>
|
||||
<string name="screen_notification_optin_subtitle">"A beállításokat később is módosíthatja."</string>
|
||||
<string name="screen_notification_optin_title">"Értesítések engedélyezése, hogy soha ne maradjon le egyetlen üzenetről sem"</string>
|
||||
<string name="screen_welcome_bullet_1">"A hívások, szavazások, keresések és egyebek az év további részében kerülnek hozzáadásra."</string>
|
||||
<string name="screen_welcome_bullet_2">"A titkosított szobák üzenetelőzményei nem lesznek elérhetők ebben a frissítésben."</string>
|
||||
<string name="screen_welcome_bullet_3">"Szeretnénk hallani a véleményét, ossza meg velünk a beállítások oldalon."</string>
|
||||
<string name="screen_welcome_button">"Lássunk neki!"</string>
|
||||
<string name="screen_welcome_subtitle">"A következőket kell tudnia:"</string>
|
||||
<string name="screen_welcome_title">"Üdvözli az %1$s!"</string>
|
||||
</resources>
|
||||
13
features/ftue/impl/src/main/res/values-in/translations.xml
Normal file
13
features/ftue/impl/src/main/res/values-in/translations.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_migration_message">"Ini adalah proses satu kali, terima kasih telah menunggu."</string>
|
||||
<string name="screen_migration_title">"Menyiapkan akun Anda."</string>
|
||||
<string name="screen_notification_optin_subtitle">"Anda dapat mengubah pengaturan Anda nanti."</string>
|
||||
<string name="screen_notification_optin_title">"Izinkan pemberitahuan dan jangan pernah melewatkan pesan"</string>
|
||||
<string name="screen_welcome_bullet_1">"Panggilan, pemungutan suara, pencarian, dan lainnya akan ditambahkan di tahun ini."</string>
|
||||
<string name="screen_welcome_bullet_2">"Riwayat pesan untuk ruangan terenkripsi tidak akan tersedia dalam pembaruan ini."</string>
|
||||
<string name="screen_welcome_bullet_3">"Kami ingin mendengar dari Anda, beri tahu kami pendapat Anda melalui halaman pengaturan."</string>
|
||||
<string name="screen_welcome_button">"Ayo!"</string>
|
||||
<string name="screen_welcome_subtitle">"Berikut adalah yang perlu Anda ketahui:"</string>
|
||||
<string name="screen_welcome_title">"Selamat datang di %1$s!"</string>
|
||||
</resources>
|
||||
|
|
@ -20,7 +20,7 @@ import android.os.Build
|
|||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.permissions.api.PermissionStateProvider
|
||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||
import io.element.android.libraries.permissions.impl.FakePermissionStateProvider
|
||||
|
|
@ -52,7 +52,7 @@ class NotificationsOptInPresenterTests {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.notificationsPermissionState.showDialog).isFalse()
|
||||
assertThat(initialState.notificationsPermissionState.showDialog).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ class NotificationsOptInPresenterTests {
|
|||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(NotificationsOptInEvents.ContinueClicked)
|
||||
Truth.assertThat(awaitItem().notificationsPermissionState.showDialog).isTrue()
|
||||
assertThat(awaitItem().notificationsPermissionState.showDialog).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ class NotificationsOptInPresenterTests {
|
|||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(NotificationsOptInEvents.ContinueClicked)
|
||||
Truth.assertThat(isFinished).isTrue()
|
||||
assertThat(isFinished).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ class NotificationsOptInPresenterTests {
|
|||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(NotificationsOptInEvents.NotNowClicked)
|
||||
Truth.assertThat(isFinished).isTrue()
|
||||
assertThat(isFinished).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ class NotificationsOptInPresenterTests {
|
|||
val isPermissionDenied = runBlocking {
|
||||
permissionStateProvider.isPermissionDenied("notifications").first()
|
||||
}
|
||||
Truth.assertThat(isPermissionDenied).isTrue()
|
||||
assertThat(isPermissionDenied).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ data class InviteListInviteSummary(
|
|||
val isNew: Boolean = false,
|
||||
)
|
||||
|
||||
data class InviteSender constructor(
|
||||
data class InviteSender(
|
||||
val userId: UserId,
|
||||
val displayName: String,
|
||||
val avatarData: AvatarData = AvatarData(userId.value, displayName, size = AvatarSize.InviteSender),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_decline_chat_message">"Biztos, hogy elutasítja a meghívást, hogy csatlakozzon ehhez: %1$s?"</string>
|
||||
<string name="screen_invites_decline_chat_title">"Meghívás elutasítása"</string>
|
||||
<string name="screen_invites_decline_direct_chat_message">"Biztos, hogy elutasítja ezt a privát csevegést vele: %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Csevegés elutasítása"</string>
|
||||
<string name="screen_invites_empty_list">"Nincsenek meghívások"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) meghívta"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_decline_chat_message">"Apakah Anda yakin ingin menolak undangan untuk bergabung ke %1$s?"</string>
|
||||
<string name="screen_invites_decline_chat_title">"Tolak undangan"</string>
|
||||
<string name="screen_invites_decline_direct_chat_message">"Apakah Anda yakin ingin menolak obrolan pribadi dengan %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Tolak obrolan"</string>
|
||||
<string name="screen_invites_empty_list">"Tidak ada undangan"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) mengundang Anda"</string>
|
||||
</resources>
|
||||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.invitelist.impl
|
|||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.invitelist.api.SeenInvitesStore
|
||||
import io.element.android.features.invitelist.test.FakeSeenInvitesStore
|
||||
import io.element.android.libraries.architecture.Async
|
||||
|
|
@ -63,14 +63,14 @@ class InviteListPresenterTests {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.inviteList).isEmpty()
|
||||
assertThat(initialState.inviteList).isEmpty()
|
||||
|
||||
roomListService.postInviteRooms(listOf(aRoomSummary()))
|
||||
|
||||
val withInviteState = awaitItem()
|
||||
Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,11 +84,11 @@ class InviteListPresenterTests {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val withInviteState = awaitItem()
|
||||
Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomAlias).isEqualTo(A_USER_ID.value)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomAvatarData).isEqualTo(
|
||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
assertThat(withInviteState.inviteList[0].roomAlias).isEqualTo(A_USER_ID.value)
|
||||
assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
||||
assertThat(withInviteState.inviteList[0].roomAvatarData).isEqualTo(
|
||||
AvatarData(
|
||||
id = A_USER_ID.value,
|
||||
name = A_USER_NAME,
|
||||
|
|
@ -96,7 +96,7 @@ class InviteListPresenterTests {
|
|||
size = AvatarSize.RoomInviteItem,
|
||||
)
|
||||
)
|
||||
Truth.assertThat(withInviteState.inviteList[0].sender).isNull()
|
||||
assertThat(withInviteState.inviteList[0].sender).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,10 +110,10 @@ class InviteListPresenterTests {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val withInviteState = awaitItem()
|
||||
Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
Truth.assertThat(withInviteState.inviteList[0].sender?.displayName).isEqualTo(A_USER_NAME)
|
||||
Truth.assertThat(withInviteState.inviteList[0].sender?.userId).isEqualTo(A_USER_ID)
|
||||
Truth.assertThat(withInviteState.inviteList[0].sender?.avatarData).isEqualTo(
|
||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
||||
assertThat(withInviteState.inviteList[0].sender?.displayName).isEqualTo(A_USER_NAME)
|
||||
assertThat(withInviteState.inviteList[0].sender?.userId).isEqualTo(A_USER_ID)
|
||||
assertThat(withInviteState.inviteList[0].sender?.avatarData).isEqualTo(
|
||||
AvatarData(
|
||||
id = A_USER_ID.value,
|
||||
name = A_USER_NAME,
|
||||
|
|
@ -142,11 +142,11 @@ class InviteListPresenterTests {
|
|||
originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0]))
|
||||
|
||||
val newState = awaitItem()
|
||||
Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
|
||||
assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
|
||||
|
||||
val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible
|
||||
Truth.assertThat(confirmDialog.isDirect).isTrue()
|
||||
Truth.assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
|
||||
assertThat(confirmDialog.isDirect).isTrue()
|
||||
assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +163,11 @@ class InviteListPresenterTests {
|
|||
originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0]))
|
||||
|
||||
val newState = awaitItem()
|
||||
Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
|
||||
assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
|
||||
|
||||
val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible
|
||||
Truth.assertThat(confirmDialog.isDirect).isFalse()
|
||||
Truth.assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
|
||||
assertThat(confirmDialog.isDirect).isFalse()
|
||||
assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ class InviteListPresenterTests {
|
|||
originalState.eventSink(InviteListEvents.CancelDeclineInvite)
|
||||
|
||||
val newState = awaitItem()
|
||||
Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Hidden::class.java)
|
||||
assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Hidden::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ class InviteListPresenterTests {
|
|||
|
||||
skipItems(2)
|
||||
|
||||
Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
|
||||
assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ class InviteListPresenterTests {
|
|||
|
||||
val newState = awaitItem()
|
||||
|
||||
Truth.assertThat(newState.declinedAction).isEqualTo(Async.Failure<Unit>(ex))
|
||||
assertThat(newState.declinedAction).isEqualTo(Async.Failure<Unit>(ex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ class InviteListPresenterTests {
|
|||
|
||||
val newState = awaitItem()
|
||||
|
||||
Truth.assertThat(newState.declinedAction).isEqualTo(Async.Uninitialized)
|
||||
assertThat(newState.declinedAction).isEqualTo(Async.Uninitialized)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -300,8 +300,8 @@ class InviteListPresenterTests {
|
|||
|
||||
val newState = awaitItem()
|
||||
|
||||
Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
|
||||
assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ class InviteListPresenterTests {
|
|||
val originalState = awaitItem()
|
||||
originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0]))
|
||||
|
||||
Truth.assertThat(awaitItem().acceptedAction).isEqualTo(Async.Failure<RoomId>(ex))
|
||||
assertThat(awaitItem().acceptedAction).isEqualTo(Async.Failure<RoomId>(ex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ class InviteListPresenterTests {
|
|||
originalState.eventSink(InviteListEvents.DismissAcceptError)
|
||||
|
||||
val newState = awaitItem()
|
||||
Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Uninitialized)
|
||||
assertThat(newState.acceptedAction).isEqualTo(Async.Uninitialized)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -375,19 +375,19 @@ class InviteListPresenterTests {
|
|||
roomListService.postInviteRooms(listOf(aRoomSummary()))
|
||||
|
||||
awaitItem()
|
||||
Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
|
||||
assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
|
||||
|
||||
// When a second is added, both are saved
|
||||
roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
|
||||
|
||||
awaitItem()
|
||||
Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
|
||||
assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
|
||||
|
||||
// When they're both dismissed, an empty set is saved
|
||||
roomListService.postInviteRooms(listOf())
|
||||
|
||||
awaitItem()
|
||||
Truth.assertThat(store.getProvidedRoomIds()).isEmpty()
|
||||
assertThat(store.getProvidedRoomIds()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -413,11 +413,11 @@ class InviteListPresenterTests {
|
|||
skipItems(1)
|
||||
|
||||
val withInviteState = awaitItem()
|
||||
Truth.assertThat(withInviteState.inviteList.size).isEqualTo(2)
|
||||
Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
Truth.assertThat(withInviteState.inviteList[0].isNew).isFalse()
|
||||
Truth.assertThat(withInviteState.inviteList[1].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
Truth.assertThat(withInviteState.inviteList[1].isNew).isTrue()
|
||||
assertThat(withInviteState.inviteList.size).isEqualTo(2)
|
||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
||||
assertThat(withInviteState.inviteList[0].isNew).isFalse()
|
||||
assertThat(withInviteState.inviteList[1].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
assertThat(withInviteState.inviteList[1].isNew).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="leave_room_alert_empty_subtitle">"Biztos, hogy elhagyja ezt a szobát? Ön az egyedüli ember itt. Ha kilép, akkor senki sem fog tudni csatlakozni a jövőben, Önt is beleértve."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Biztos, hogy elhagyja ezt a szobát? Ez a szoba nem nyilvános, és meghívó nélkül nem fog tudni újra belépni."</string>
|
||||
<string name="leave_room_alert_subtitle">"Biztos, hogy elhagyja a szobát?"</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="leave_room_alert_empty_subtitle">"Apakah Anda yakin ingin meninggalkan ruangan ini? Anda adalah orang satu-satunya di sini. Jika Anda pergi, tidak akan ada yang bisa bergabung di masa depan, termasuk Anda."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Apakah Anda yakin ingin meninggalkan ruangan ini? Ruangan ini tidak umum dan Anda tidak akan dapat bergabung kembali tanpa undangan."</string>
|
||||
<string name="leave_room_alert_subtitle">"Apakah Anda yakin ingin meninggalkan ruangan?"</string>
|
||||
</resources>
|
||||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.location.impl.send
|
|||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.Composer
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.aPermissionsState
|
||||
|
|
@ -77,16 +77,16 @@ class SendLocationPresenterTest {
|
|||
}.test {
|
||||
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
|
||||
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
|
||||
assertThat(initialState.hasLocationPermission).isTrue()
|
||||
|
||||
// Swipe the map to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToPinLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(true)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,16 +104,16 @@ class SendLocationPresenterTest {
|
|||
}.test {
|
||||
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
|
||||
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
|
||||
assertThat(initialState.hasLocationPermission).isTrue()
|
||||
|
||||
// Swipe the map to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToPinLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(true)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,16 +130,16 @@ class SendLocationPresenterTest {
|
|||
sendLocationPresenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(initialState.hasLocationPermission).isFalse()
|
||||
|
||||
// Click on the button to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,16 +156,16 @@ class SendLocationPresenterTest {
|
|||
sendLocationPresenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(initialState.hasLocationPermission).isFalse()
|
||||
|
||||
// Click on the button to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,16 +187,16 @@ class SendLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Dismiss the dialog
|
||||
myLocationState.eventSink(SendLocationEvents.DismissDialog)
|
||||
val dialogDismissedState = awaitItem()
|
||||
Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(dialogDismissedState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,13 +218,13 @@ class SendLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Continue the dialog sends permission request to the permissions presenter
|
||||
myLocationState.eventSink(SendLocationEvents.RequestPermissions)
|
||||
Truth.assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
|
||||
assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,16 +246,16 @@ class SendLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
|
||||
val myLocationState = awaitItem()
|
||||
Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
|
||||
Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
|
||||
assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(myLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Dismiss the dialog
|
||||
myLocationState.eventSink(SendLocationEvents.DismissDialog)
|
||||
val dialogDismissedState = awaitItem()
|
||||
Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
|
||||
assertThat(dialogDismissedState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -292,8 +292,8 @@ class SendLocationPresenterTest {
|
|||
|
||||
delay(1) // Wait for the coroutine to finish
|
||||
|
||||
Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
|
||||
Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
|
||||
assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
|
||||
assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
|
||||
SendLocationInvocation(
|
||||
body = "Location was shared at geo:3.0,4.0;u=5.0",
|
||||
geoUri = "geo:3.0,4.0;u=5.0",
|
||||
|
|
@ -303,8 +303,8 @@ class SendLocationPresenterTest {
|
|||
)
|
||||
)
|
||||
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
Composer(
|
||||
inThread = false,
|
||||
isEditing = false,
|
||||
|
|
@ -348,8 +348,8 @@ class SendLocationPresenterTest {
|
|||
|
||||
delay(1) // Wait for the coroutine to finish
|
||||
|
||||
Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
|
||||
Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
|
||||
assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
|
||||
assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
|
||||
SendLocationInvocation(
|
||||
body = "Location was shared at geo:0.0,1.0",
|
||||
geoUri = "geo:0.0,1.0",
|
||||
|
|
@ -359,8 +359,8 @@ class SendLocationPresenterTest {
|
|||
)
|
||||
)
|
||||
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
Composer(
|
||||
inThread = false,
|
||||
isEditing = false,
|
||||
|
|
@ -405,8 +405,8 @@ class SendLocationPresenterTest {
|
|||
|
||||
delay(1) // Wait for the coroutine to finish
|
||||
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
|
||||
Composer(
|
||||
inThread = false,
|
||||
isEditing = true,
|
||||
|
|
@ -444,8 +444,8 @@ class SendLocationPresenterTest {
|
|||
dialogShownState.eventSink(SendLocationEvents.OpenAppSettings)
|
||||
val settingsOpenedState = awaitItem()
|
||||
|
||||
Truth.assertThat(settingsOpenedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
Truth.assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
|
||||
assertThat(settingsOpenedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
|
||||
assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ class SendLocationPresenterTest {
|
|||
sendLocationPresenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.appName).isEqualTo("app name")
|
||||
assertThat(initialState.appName).isEqualTo("app name")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.location.impl.show
|
|||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.aPermissionsState
|
||||
import io.element.android.features.location.impl.common.actions.FakeLocationActions
|
||||
|
|
@ -66,10 +66,10 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.location).isEqualTo(location)
|
||||
Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
|
||||
Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
|
||||
assertThat(initialState.location).isEqualTo(location)
|
||||
assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
assertThat(initialState.hasLocationPermission).isFalse()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,10 +86,10 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.location).isEqualTo(location)
|
||||
Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
|
||||
Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
|
||||
assertThat(initialState.location).isEqualTo(location)
|
||||
assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
assertThat(initialState.hasLocationPermission).isFalse()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,10 +101,10 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.location).isEqualTo(location)
|
||||
Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
|
||||
Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
|
||||
assertThat(initialState.location).isEqualTo(location)
|
||||
assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
assertThat(initialState.hasLocationPermission).isTrue()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,10 +116,10 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.location).isEqualTo(location)
|
||||
Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
|
||||
Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
|
||||
assertThat(initialState.location).isEqualTo(location)
|
||||
assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
|
||||
assertThat(initialState.hasLocationPermission).isTrue()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,8 +131,8 @@ class ShowLocationPresenterTest {
|
|||
val initialState = awaitItem()
|
||||
initialState.eventSink(ShowLocationEvents.Share)
|
||||
|
||||
Truth.assertThat(fakeLocationActions.sharedLocation).isEqualTo(location)
|
||||
Truth.assertThat(fakeLocationActions.sharedLabel).isEqualTo(A_DESCRIPTION)
|
||||
assertThat(fakeLocationActions.sharedLocation).isEqualTo(location)
|
||||
assertThat(fakeLocationActions.sharedLabel).isEqualTo(A_DESCRIPTION)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,23 +144,23 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
|
||||
Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
|
||||
assertThat(initialState.hasLocationPermission).isTrue()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
|
||||
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
|
||||
val trackMyLocationState = awaitItem()
|
||||
|
||||
delay(1)
|
||||
|
||||
Truth.assertThat(trackMyLocationState.hasLocationPermission).isEqualTo(true)
|
||||
Truth.assertThat(trackMyLocationState.isTrackMyLocation).isEqualTo(true)
|
||||
assertThat(trackMyLocationState.hasLocationPermission).isTrue()
|
||||
assertThat(trackMyLocationState.isTrackMyLocation).isTrue()
|
||||
|
||||
// Swipe the map to switch mode
|
||||
initialState.eventSink(ShowLocationEvents.TrackMyLocation(false))
|
||||
val trackLocationDisabledState = awaitItem()
|
||||
Truth.assertThat(trackLocationDisabledState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
Truth.assertThat(trackLocationDisabledState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(trackLocationDisabledState.hasLocationPermission).isEqualTo(true)
|
||||
assertThat(trackLocationDisabledState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
assertThat(trackLocationDisabledState.isTrackMyLocation).isFalse()
|
||||
assertThat(trackLocationDisabledState.hasLocationPermission).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,16 +182,16 @@ class ShowLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
|
||||
val trackLocationState = awaitItem()
|
||||
Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
|
||||
Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
|
||||
assertThat(trackLocationState.isTrackMyLocation).isFalse()
|
||||
assertThat(trackLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Dismiss the dialog
|
||||
initialState.eventSink(ShowLocationEvents.DismissDialog)
|
||||
val dialogDismissedState = awaitItem()
|
||||
Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
assertThat(dialogDismissedState.isTrackMyLocation).isFalse()
|
||||
assertThat(dialogDismissedState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,13 +213,13 @@ class ShowLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
|
||||
val trackLocationState = awaitItem()
|
||||
Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
|
||||
Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
|
||||
assertThat(trackLocationState.isTrackMyLocation).isFalse()
|
||||
assertThat(trackLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Continue the dialog sends permission request to the permissions presenter
|
||||
trackLocationState.eventSink(ShowLocationEvents.RequestPermissions)
|
||||
Truth.assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
|
||||
assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,16 +241,16 @@ class ShowLocationPresenterTest {
|
|||
// Click on the button to switch mode
|
||||
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
|
||||
val trackLocationState = awaitItem()
|
||||
Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionDenied)
|
||||
Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionDenied)
|
||||
assertThat(trackLocationState.isTrackMyLocation).isFalse()
|
||||
assertThat(trackLocationState.hasLocationPermission).isFalse()
|
||||
|
||||
// Dismiss the dialog
|
||||
initialState.eventSink(ShowLocationEvents.DismissDialog)
|
||||
val dialogDismissedState = awaitItem()
|
||||
Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false)
|
||||
Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
|
||||
assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
assertThat(dialogDismissedState.isTrackMyLocation).isFalse()
|
||||
assertThat(dialogDismissedState.hasLocationPermission).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +276,8 @@ class ShowLocationPresenterTest {
|
|||
dialogShownState.eventSink(ShowLocationEvents.OpenAppSettings)
|
||||
val settingsOpenedState = awaitItem()
|
||||
|
||||
Truth.assertThat(settingsOpenedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
Truth.assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
|
||||
assertThat(settingsOpenedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
|
||||
assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ class ShowLocationPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
Truth.assertThat(initialState.appName).isEqualTo("app name")
|
||||
assertThat(initialState.appName).isEqualTo("app name")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"Du hast %1$d Versuch zu entsperren"</item>
|
||||
<item quantity="other">"Du hast %1$d Versuche zum Entsperren"</item>
|
||||
</plurals>
|
||||
<plurals name="screen_app_lock_subtitle_wrong_pin">
|
||||
<item quantity="one">"Falsche PIN. Du hast %1$d weitere Chance"</item>
|
||||
<item quantity="other">"Falsche PIN. Du hast %1$d weitere Chancen"</item>
|
||||
</plurals>
|
||||
<string name="screen_app_lock_biometric_authentication">"biometrische Authentifizierung"</string>
|
||||
<string name="screen_app_lock_biometric_unlock">"biometrisches Entsperren"</string>
|
||||
<string name="screen_app_lock_biometric_unlock_title_android">"Mit Biometrie entsperren"</string>
|
||||
<string name="screen_app_lock_forgot_pin">"PIN vergessen?"</string>
|
||||
<string name="screen_app_lock_settings_change_pin">"PIN-Code ändern"</string>
|
||||
<string name="screen_app_lock_settings_enable_biometric_unlock">"Biometrisches Entsperren zulassen"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin">"Pin entfernen"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_message">"Bist du sicher, dass du die PIN entfernen willst?"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_title">"PIN entfernen?"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_allow_title">"%1$s zulassen"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_skip">"Ich verwende lieber die PIN"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"Spare dir etwas Zeit und benutze %1$s, um die App jedes Mal zu entsperren"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"PIN wählen"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"PIN bestätigen"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_content">"Aus Sicherheitsgründen kannst du das nicht als deinen PIN-Code wählen"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_title">"Wähle eine andere PIN"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Sperre %1$s, um deine Chats noch sicherer zu machen.
|
||||
|
||||
Wähle etwas Einprägsames. Wenn du diese PIN vergisst, wirst du aus der App ausgeloggt."</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Bitte gib die gleiche PIN zweimal ein"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"Die PINs stimmen nicht überein"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Um fortzufahren, musst du dich erneut anmelden und eine neue PIN erstellen"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Du wirst abgemeldet"</string>
|
||||
<string name="screen_app_lock_use_biometric_android">"Biometrie verwenden"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"PIN verwenden"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Abmelden…"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"%1$d próbálkozása van a feloldáshoz"</item>
|
||||
<item quantity="other">"%1$d próbálkozása van a feloldáshoz"</item>
|
||||
</plurals>
|
||||
<plurals name="screen_app_lock_subtitle_wrong_pin">
|
||||
<item quantity="one">"Hibás PIN-kód. Még %1$d próbálkozási lehetősége maradt."</item>
|
||||
<item quantity="other">"Hibás PIN-kód. Még %1$d próbálkozási lehetősége maradt."</item>
|
||||
</plurals>
|
||||
<string name="screen_app_lock_biometric_authentication">"biometrikus hitelesítés"</string>
|
||||
<string name="screen_app_lock_biometric_unlock">"biometrikus feloldás"</string>
|
||||
<string name="screen_app_lock_biometric_unlock_title_android">"Feloldás biometrikus adatokkal"</string>
|
||||
<string name="screen_app_lock_forgot_pin">"Elfelejtette a PIN-kódot?"</string>
|
||||
<string name="screen_app_lock_settings_change_pin">"PIN-kód módosítása"</string>
|
||||
<string name="screen_app_lock_settings_enable_biometric_unlock">"Biometrikus feloldás engedélyezése"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin">"PIN-kód eltávolítása"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_message">"Biztos, hogy eltávolítja a PIN-kódot?"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_title">"PIN-kód eltávolítása?"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_allow_title">"A %1$s engedélyezése"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_skip">"Inkább PIN-kód használata"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"Spóroljon meg némi időt, és használja a %1$st az alkalmazás feloldásához"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"PIN-kód kiválasztása"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"PIN-kód megerősítése"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_content">"Ezt biztonsági okokból nem választhatja PIN-kódként"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_title">"Válasszon egy másik PIN-kódot"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Az %1$s zárolása a csevegései nagyobb biztonsága érdekében.
|
||||
|
||||
Válasszon valami megjegyezhetőt. Ha elfelejti a PIN-kódot, akkor ki lesz jelentkeztetve az alkalmazásból."</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Adja meg a PIN-kódját kétszer"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"A PIN-kódok nem egyeznek"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"A folytatáshoz újra be kell jelentkeznie, és létre kell hoznia egy új PIN-kódot"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Kijelentkeztetésre kerül"</string>
|
||||
<string name="screen_app_lock_use_biometric_android">"Biometrikus adatok használata"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"PIN-kód használata"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Kijelentkezés…"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="other">"Anda memiliki %1$d percobaan lagi untuk membuka kunci"</item>
|
||||
</plurals>
|
||||
<plurals name="screen_app_lock_subtitle_wrong_pin">
|
||||
<item quantity="other">"PIN salah. Anda memiliki %1$d percobaan lagi"</item>
|
||||
</plurals>
|
||||
<string name="screen_app_lock_biometric_authentication">"autentikasi biometrik"</string>
|
||||
<string name="screen_app_lock_biometric_unlock">"pembukaan biometrik"</string>
|
||||
<string name="screen_app_lock_biometric_unlock_title_android">"Buka kunci dengan biometrik"</string>
|
||||
<string name="screen_app_lock_forgot_pin">"Lupa PIN?"</string>
|
||||
<string name="screen_app_lock_settings_change_pin">"Ubah kode PIN"</string>
|
||||
<string name="screen_app_lock_settings_enable_biometric_unlock">"Perbolehkan pembukaan biometrik"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin">"Hapus PIN"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_message">"Apakah Anda yakin ingin menghapus PIN?"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_title">"Hapus PIN?"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_allow_title">"Perbolehkan %1$s"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_skip">"Saya lebih suka menggunakan PIN"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"Hemat waktu Anda dan gunakan %1$s untuk membuka kunci aplikasi setiap kalinya"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"Pilih PIN"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"Konfirmasi PIN"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_content">"Anda tidak dapat memilih PIN ini demi keamanan"</string>
|
||||
<string name="screen_app_lock_setup_pin_blacklisted_dialog_title">"Pilih PIN yang lain"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Kunci %1$s untuk menambahkan keamanan tambahan pada percakapan Anda.
|
||||
|
||||
Pilih sesuatu yang mudah untuk diingat. Jika Anda lupa PIN ini, Anda akan dikeluarkan dari aplikasi."</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Silakan masukkan PIN yang sama dua kali"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"PIN tidak cocok"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Anda harus masuk ulang dan membuat PIN baru untuk melanjutkan"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Anda sedang dikeluarkan"</string>
|
||||
<string name="screen_app_lock_use_biometric_android">"Gunakan biometrik"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"Gunakan PIN"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Mengeluarkan dari akun…"</string>
|
||||
</resources>
|
||||
|
|
@ -94,8 +94,8 @@ class PinUnlockPresenterTest {
|
|||
}
|
||||
awaitLastSequentialItem().also { state ->
|
||||
assertThat(state.remainingAttempts.dataOrNull()).isEqualTo(0)
|
||||
assertThat(state.showSignOutPrompt).isEqualTo(true)
|
||||
assertThat(state.isSignOutPromptCancellable).isEqualTo(false)
|
||||
assertThat(state.showSignOutPrompt).isTrue()
|
||||
assertThat(state.isSignOutPromptCancellable).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -112,16 +112,16 @@ class PinUnlockPresenterTest {
|
|||
state.eventSink(PinUnlockEvents.OnForgetPin)
|
||||
}
|
||||
awaitLastSequentialItem().also { state ->
|
||||
assertThat(state.showSignOutPrompt).isEqualTo(true)
|
||||
assertThat(state.isSignOutPromptCancellable).isEqualTo(true)
|
||||
assertThat(state.showSignOutPrompt).isTrue()
|
||||
assertThat(state.isSignOutPromptCancellable).isTrue()
|
||||
state.eventSink(PinUnlockEvents.ClearSignOutPrompt)
|
||||
}
|
||||
awaitLastSequentialItem().also { state ->
|
||||
assertThat(state.showSignOutPrompt).isEqualTo(false)
|
||||
assertThat(state.showSignOutPrompt).isFalse()
|
||||
state.eventSink(PinUnlockEvents.OnForgetPin)
|
||||
}
|
||||
awaitLastSequentialItem().also { state ->
|
||||
assertThat(state.showSignOutPrompt).isEqualTo(true)
|
||||
assertThat(state.showSignOutPrompt).isTrue()
|
||||
state.eventSink(PinUnlockEvents.SignOut)
|
||||
}
|
||||
consumeItemsUntilPredicate { state ->
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.resolver
|
||||
|
||||
data class HomeserverData constructor(
|
||||
data class HomeserverData(
|
||||
// The computed homeserver url, for which a wellknown file has been retrieved, or just a valid Url
|
||||
val homeserverUrl: String,
|
||||
// True if a wellknown file has been found and is valid. If false, it means that the [homeserverUrl] is valid
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<string name="screen_change_server_form_header">"Homeserver-URL"</string>
|
||||
<string name="screen_change_server_form_notice">"Du kannst nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Dein Homeserver-Administrator muss das konfigurieren. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Wie lautet die Adresse deines Servers?"</string>
|
||||
<string name="screen_change_server_title">"Wähle deinen Server aus"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Dieses Konto wurde deaktiviert."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Falscher Benutzername und/oder Passwort"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@user:homeserver.org\'"</string>
|
||||
|
|
|
|||
42
features/login/impl/src/main/res/values-hu/translations.xml
Normal file
42
features/login/impl/src/main/res/values-hu/translations.xml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_account_provider_change">"Fiókszolgáltató módosítása"</string>
|
||||
<string name="screen_account_provider_form_hint">"Matrix-kiszolgáló webcíme"</string>
|
||||
<string name="screen_account_provider_form_notice">"Adjon meg egy keresési kifejezést vagy egy tartománycímet."</string>
|
||||
<string name="screen_account_provider_form_subtitle">"Keresés egy cégre, közösségre vagy privát kiszolgálóra."</string>
|
||||
<string name="screen_account_provider_form_title">"Fiókszolgáltató keresése"</string>
|
||||
<string name="screen_account_provider_signin_subtitle">"Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."</string>
|
||||
<string name="screen_account_provider_signin_title">"Hamarosan bejelentkezik ide: %s"</string>
|
||||
<string name="screen_account_provider_signup_subtitle">"Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."</string>
|
||||
<string name="screen_account_provider_signup_title">"Hamarosan létrehoz egy fiókot itt: %s"</string>
|
||||
<string name="screen_change_account_provider_matrix_org_subtitle">"A Matrix.org egy nagy, ingyenes kiszolgáló a nyilvános Matrix-hálózaton, a biztonságos, decentralizált kommunikáció érdekében, amelyet a Matrix.org Alapítvány üzemeltet."</string>
|
||||
<string name="screen_change_account_provider_other">"Egyéb"</string>
|
||||
<string name="screen_change_account_provider_subtitle">"Másik fiókszolgáltató, például a saját privát kiszolgáló vagy egy munkahelyi fiók használata."</string>
|
||||
<string name="screen_change_account_provider_title">"Fiókszolgáltató módosítása"</string>
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Nem sikerült elérni ezt a Matrix-kiszolgálót. Ellenőrizze, hogy helyesen adta-e meg a Matrix-kiszolgáló webcímét. Ha a webcím helyes, akkor további segítségért lépjen kapcsolatba a Matrix-kiszolgáló rendszergazdájával."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"A kiszolgáló jelenleg nem támogatja a Sliding sync protokollt."</string>
|
||||
<string name="screen_change_server_form_header">"Matrix-kiszolgáló webcíme"</string>
|
||||
<string name="screen_change_server_form_notice">"Csak olyan meglévő kiszolgálóhoz csatlakozhat, amely támogatja a Sliding sync protokollt. Ezt a Matrix-kiszolgáló rendszergazdájának kell beállítania. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Mi a kiszolgálója címe?"</string>
|
||||
<string name="screen_change_server_title">"Válassza ki a kiszolgálóját"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Ez a fiók deaktiválva lett."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Helytelen felhasználónév vagy jelszó"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Ez nem érvényes felhasználóazonosító. A várt formátum: „@user:homeserver.org”"</string>
|
||||
<string name="screen_login_error_unsupported_authentication">"A kiválasztott Matrix-kiszolgáló nem támogatja a jelszavas vagy OIDC-alapú bejelentkezést. Lépjen kapcsolatba a kiszolgáló rendszergazdájával, vagy válasszon másik Matrix-kiszolgálót."</string>
|
||||
<string name="screen_login_form_header">"Adja meg adatait"</string>
|
||||
<string name="screen_login_title">"Örülünk, hogy visszatért!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"Bejelentkezés ide: %1$s"</string>
|
||||
<string name="screen_server_confirmation_change_server">"Fiókszolgáltató módosítása"</string>
|
||||
<string name="screen_server_confirmation_message_login_element_dot_io">"Egy privát kiszolgáló az Element alkalmazottai számára."</string>
|
||||
<string name="screen_server_confirmation_message_login_matrix_dot_org">"A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz."</string>
|
||||
<string name="screen_server_confirmation_message_register">"Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."</string>
|
||||
<string name="screen_server_confirmation_title_login">"Hamarosan bejelentkezik ebbe: %1$s"</string>
|
||||
<string name="screen_server_confirmation_title_register">"Hamarosan létrehoz egy fiókot ezen: %1$s"</string>
|
||||
<string name="screen_waitlist_message">"Jelenleg nagy a kereslet a(z) %2$s oldalon futó %1$s iránt. Térjen vissza néhány nap múlva az alkalmazáshoz, és próbálja újra.
|
||||
|
||||
Köszönjük a türelmét!"</string>
|
||||
<string name="screen_waitlist_title">"Már majdnem kész van."</string>
|
||||
<string name="screen_waitlist_title_success">"Bent van."</string>
|
||||
<string name="screen_login_subtitle">"A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz."</string>
|
||||
<string name="screen_waitlist_message_success">"Üdvözli az %1$s!"</string>
|
||||
</resources>
|
||||
42
features/login/impl/src/main/res/values-in/translations.xml
Normal file
42
features/login/impl/src/main/res/values-in/translations.xml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_account_provider_change">"Ubah penyedia akun"</string>
|
||||
<string name="screen_account_provider_form_hint">"Alamat homeserver"</string>
|
||||
<string name="screen_account_provider_form_notice">"Masukkan istilah pencarian atau alamat domain."</string>
|
||||
<string name="screen_account_provider_form_subtitle">"Cari perusahaan, komunitas, atau server pribadi."</string>
|
||||
<string name="screen_account_provider_form_title">"Cari penyedia akun"</string>
|
||||
<string name="screen_account_provider_signin_subtitle">"Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."</string>
|
||||
<string name="screen_account_provider_signin_title">"Anda akan masuk ke %s"</string>
|
||||
<string name="screen_account_provider_signup_subtitle">"Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."</string>
|
||||
<string name="screen_account_provider_signup_title">"Anda akan membuat akun di %s"</string>
|
||||
<string name="screen_change_account_provider_matrix_org_subtitle">"Matrix.org adalah server besar dan gratis di jaringan Matrix publik untuk komunikasi yang aman dan terdesentralisasi, disediakan oleh Yayasan Matrix.org."</string>
|
||||
<string name="screen_change_account_provider_other">"Lainnya"</string>
|
||||
<string name="screen_change_account_provider_subtitle">"Gunakan penyedia akun yang berbeda, seperti server pribadi Anda sendiri atau akun kerja."</string>
|
||||
<string name="screen_change_account_provider_title">"Ubah penyedia akun"</string>
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Kami tidak dapat menjangkau server ini. Periksa apakah Anda telah memasukkan URL homeserver dengan benar. Jika URL sudah benar, hubungi administrator homeserver Anda untuk bantuan lebih lanjut."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Server ini saat ini tidak mendukung sinkronisasi geser."</string>
|
||||
<string name="screen_change_server_form_header">"URL Homeserver"</string>
|
||||
<string name="screen_change_server_form_notice">"Anda hanya dapat terhubung ke server yang ada yang mendukung sinkronisasi geser. Admin homeserver Anda perlu mengaturnya. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Apa alamat server Anda?"</string>
|
||||
<string name="screen_change_server_title">"Pilih server Anda"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Akun ini telah dinonaktifkan."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Nama pengguna dan/atau kata sandi salah"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Ini bukan pengenal pengguna yang valid. Format yang diharapkan: \'@pengguna:homeserver.org\'"</string>
|
||||
<string name="screen_login_error_unsupported_authentication">"Homeserver yang dipilih tidak mendukung log masuk kata sandi atau OIDC. Silakan hubungi admin Anda atau pilih homeserver yang lain."</string>
|
||||
<string name="screen_login_form_header">"Masukkan detail Anda"</string>
|
||||
<string name="screen_login_title">"Selamat datang kembali!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"Masuk ke %1$s"</string>
|
||||
<string name="screen_server_confirmation_change_server">"Ubah penyedia akun"</string>
|
||||
<string name="screen_server_confirmation_message_login_element_dot_io">"Server pribadi untuk karyawan Element."</string>
|
||||
<string name="screen_server_confirmation_message_login_matrix_dot_org">"Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi."</string>
|
||||
<string name="screen_server_confirmation_message_register">"Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."</string>
|
||||
<string name="screen_server_confirmation_title_login">"Anda akan masuk ke %1$s"</string>
|
||||
<string name="screen_server_confirmation_title_register">"Anda akan membuat akun di %1$s"</string>
|
||||
<string name="screen_waitlist_message">"Ada permintaan tinggi untuk %1$s di %2$s saat ini. Kembalilah ke aplikasi dalam beberapa hari dan coba lagi.
|
||||
|
||||
Terima kasih atas kesabaran Anda!"</string>
|
||||
<string name="screen_waitlist_title">"Anda hampir selesai."</string>
|
||||
<string name="screen_waitlist_title_success">"Anda sudah masuk."</string>
|
||||
<string name="screen_login_subtitle">"Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi."</string>
|
||||
<string name="screen_waitlist_message_success">"Selamat datang di %1$s!"</string>
|
||||
</resources>
|
||||
|
|
@ -2,4 +2,17 @@
|
|||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_signout_confirmation_dialog_content">"Bist du sicher, dass du dich abmelden willst?"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Abmelden…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Du hast das Backup ausgeschaltet"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Deine Schlüssel wurden noch gesichert, als du offline gegangen bist. Stelle die Verbindung wieder her, damit deine Schlüssel gesichert werden können, bevor du dich abmeldest."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Deine Schlüssel werden noch gesichert"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Bitte warte, bis der Vorgang abgeschlossen ist, bevor du dich abmeldest."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Deine Schlüssel werden noch gesichert"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Wiederherstellung nicht eingerichtet"</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du möglicherweise den Zugriff auf deine verschlüsselten Nachrichten."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Hast du deinen Wiederherstellungsschlüssel gespeichert?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Abmelden"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Abmelden"</string>
|
||||
<string name="screen_signout_preference_item">"Abmelden"</string>
|
||||
</resources>
|
||||
|
|
|
|||
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