diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml index 5cde95e625..bf948064ed 100644 --- a/.github/workflows/post-pr.yml +++ b/.github/workflows/post-pr.yml @@ -31,7 +31,7 @@ jobs: ui-tests: name: UI Tests (Synapse) needs: should-i-run - runs-on: macos-latest + runs-on: buildjet-4vcpu-ubuntu-2204 strategy: fail-fast: false matrix: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 81262f1e9f..fb8e3080ae 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,9 +1,9 @@ name: Test on: - pull_request: {} + pull_request: { } push: - branches: [main, develop] + branches: [ main, develop ] # Enrich gradle.properties for CI/CD env: @@ -13,7 +13,10 @@ env: jobs: tests: name: Runs all tests - runs-on: macos-latest # for the emulator + runs-on: buildjet-4vcpu-ubuntu-2204 + strategy: + matrix: + api-level: [28] # Allow all jobs on main and develop. Just one per PR. concurrency: group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} @@ -36,46 +39,79 @@ jobs: httpPort: 8080 disableRateLimiting: true public_baseurl: "http://10.0.2.2:8080/" + + - name: AVD cache + uses: actions/cache@v3 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ matrix.api-level }} + + - name: create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86 + profile: Nexus 5X + force-avd-creation: true # Is set to false in the doc https://github.com/ReactiveCircus/android-emulator-runner + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: echo "Generated AVD snapshot for caching." + - name: Run all the codecoverage tests at once - id: tests uses: reactivecircus/android-emulator-runner@v2 - continue-on-error: true + # continue-on-error: true with: - api-level: 28 + api-level: ${{ matrix.api-level }} arch: x86 profile: Nexus 5X force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - emulator-build: 7425822 - script: | - ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES - ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES - ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES - ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES -# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure' - - name: Run all the codecoverage tests at once (retry if emulator failed) - uses: reactivecircus/android-emulator-runner@v2 - if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded. - with: - api-level: 28 - arch: x86 - profile: Nexus 5X - force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: true - emulator-build: 7425822 + # emulator-build: 7425822 script: | ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES - - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES - if: always() # we may have failed a previous step and retried, that's OK + # NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves steps.tests.outcome = 'failure' + ### - name: Run all the codecoverage tests at once (retry if emulator failed) + ### uses: reactivecircus/android-emulator-runner@v2 + ### if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded. + ### with: + ### api-level: 28 + ### arch: x86 + ### profile: Nexus 5X + ### force-avd-creation: false + ### emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + ### disable-animations: true + ### emulator-build: 7425822 + ### script: | + ### ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES + ### ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES + ### ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES + ### ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES + + - name: Upload Integration Test Report Log + uses: actions/upload-artifact@v3 + if: always() + with: + name: integration-test-error-results + path: | + */build/outputs/androidTest-results/connected/ + */build/reports/androidTests/connected/ + + # we may have failed a previous step and retried, that's OK + - name: Publish results to Sonar env: GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} + if: ${{ always() && env.GITHUB_TOKEN != '' && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }} + run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES - name: Format unit test results if: always() diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml index f478d2bd7b..174e3c54c0 100644 --- a/.github/workflows/triage-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -142,32 +142,6 @@ jobs: env: PROJECT_ID: "PN_kwDOAM0swc2KCw" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - - move_threads_issues: - name: A-Threads to Thread board - runs-on: ubuntu-latest - # Skip in forks - if: > - github.repository == 'vector-im/element-android' && - contains(github.event.issue.labels.*.name, 'A-Threads') - steps: - - uses: octokit/graphql-action@v2.x - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - mutation add_to_project($projectid:ID!,$contentid:ID!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id - } - } - } - projectid: ${{ env.PROJECT_ID }} - contentid: ${{ github.event.issue.node_id }} - env: - PROJECT_ID: "PN_kwDOAM0swc0rRA" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - move_message_bubbles_issues: name: A-Message-Bubbles to Message bubbles board runs-on: ubuntu-latest diff --git a/.github/workflows/triage-priority-bugs.yml b/.github/workflows/triage-priority-bugs.yml index 6cde154370..e762102226 100644 --- a/.github/workflows/triage-priority-bugs.yml +++ b/.github/workflows/triage-priority-bugs.yml @@ -27,7 +27,7 @@ jobs: - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 with: project: Android App Team - column: P1 + column: Important Issues & Topics (P1) repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} P1_issues_to_crypto_team_workboard: diff --git a/CHANGES.md b/CHANGES.md index 4615ec8ff0..65e1616e2d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,105 @@ +Changes in Element v1.5.0 (2022-09-23) +====================================== + +Features ✨ +---------- + - Deferred DMs - Enable and move the feature to labs settings ([#7180](https://github.com/vector-im/element-android/issues/7180)) + +Bugfixes 🐛 +---------- + - Fix text margin in QR code view when no display name is set ([#5424](https://github.com/vector-im/element-android/issues/5424)) + - [App Layout] Recents carousel now scrolled to first position when new item added to or moved to this position ([#6776](https://github.com/vector-im/element-android/issues/6776)) + - Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items ([#7079](https://github.com/vector-im/element-android/issues/7079)) + - Fixes crash when quickly double clicking FABs in the new app layout ([#7102](https://github.com/vector-im/element-android/issues/7102)) + - Fixes space list and new chat bottom sheets showing too small in New App Layout (especially evident in landscape) ([#7103](https://github.com/vector-im/element-android/issues/7103)) + - [App Layout] Room leaving prompt dialog now waits user to confirm leaving before do so ([#7122](https://github.com/vector-im/element-android/issues/7122)) + - Fix empty verification bottom sheet. ([#7130](https://github.com/vector-im/element-android/issues/7130)) + - [New Layout] Fixes new chat dialog not getting dismissed after selecting its actions ([#7132](https://github.com/vector-im/element-android/issues/7132)) + - Fixes Room List not getting updated when fragment is not in focus ([#7186](https://github.com/vector-im/element-android/issues/7186)) + +In development 🚧 +---------------- + - Create DM room only on first message - Add a spinner when sending the first message ([#6970](https://github.com/vector-im/element-android/issues/6970)) + - [Device Manager] Filter Other Sessions ([#7045](https://github.com/vector-im/element-android/issues/7045)) + - [Device management] Session details screen ([#7077](https://github.com/vector-im/element-android/issues/7077)) + - Create DM room only on first message - Fix glitch in the room list ([#7121](https://github.com/vector-im/element-android/issues/7121)) + - Create DM room only on first message - Handle the local rooms within the new AppLayout ([#7153](https://github.com/vector-im/element-android/issues/7153)) + +Other changes +------------- + - [Modules] Lifts the application variants to the app module ([#6779](https://github.com/vector-im/element-android/issues/6779)) + - Ensure that we do not expect all the Event fields when requesting `rooms/{roomId}/hierarchy` endpoint. ([#7035](https://github.com/vector-im/element-android/issues/7035)) + - Move some GitHub actions to buildjet runners, and remove the second attempt to run integration tests. ([#7108](https://github.com/vector-im/element-android/issues/7108)) + - Exclude legacy android support annotation library ([#7140](https://github.com/vector-im/element-android/issues/7140)) + - Pulling no longer hosted im.dlg:android-dialer directly into the repository and removing legacy support library usages ([#7142](https://github.com/vector-im/element-android/issues/7142)) + - Fixing build cache misses when compiling the vector module ([#7157](https://github.com/vector-im/element-android/issues/7157)) + +Changes in Element v1.4.36 (2022-09-10) +======================================= + +New App Layout can be enabled in the Labs settings. Please give it a try! + +Features ✨ +---------- + - Adds New App Layout into Labs ([#7038](https://github.com/vector-im/element-android/issues/7038)) + - Try to detect devices that lack Opus encoder support, use bundled libopus library for those. ([#7010](https://github.com/vector-im/element-android/issues/7010)) + - Suggest @room when @channel, @everyone, or @here is typed in composer ([#6529](https://github.com/vector-im/element-android/issues/6529)) + +Bugfixes 🐛 +---------- + - Fix long incremental sync. ([#6917](https://github.com/vector-im/element-android/issues/6917)) + - Fix push with FCM ([#7068](https://github.com/vector-im/element-android/issues/7068)) + - FTUE - Fixes optional email registration step always being mandatory ([#6969](https://github.com/vector-im/element-android/issues/6969)) + - Fixes /addToSpace and /joinSpace commands showing invalid syntax warnings ([#6844](https://github.com/vector-im/element-android/issues/6844)) + - Fix low occurrence crashes. ([#6967](https://github.com/vector-im/element-android/issues/6967)) + - Fix crash when opening an unknown room ([#6978](https://github.com/vector-im/element-android/issues/6978)) + - Fix crash on PIN code settings screen. ([#6979](https://github.com/vector-im/element-android/issues/6979)) + - Fix autoplayed animated stickers ([#6982](https://github.com/vector-im/element-android/issues/6982)) + - Catch race condition crash in voice recording ([#6989](https://github.com/vector-im/element-android/issues/6989)) + - Fix invite to room when in a space buttons not working. ([#7054](https://github.com/vector-im/element-android/issues/7054)) + +In development 🚧 +---------------- + - Create DM room only on first message - Create the DM and navigate to the new room after sending an event ([#5525](https://github.com/vector-im/element-android/issues/5525)) + - [App Layout] New empty states for home screen ([#6835](https://github.com/vector-im/element-android/issues/6835)) + - [App Layout] Bottom navigation tabs are removed for new home screen ([#6565](https://github.com/vector-im/element-android/issues/6565)) + - [App Layout] fixed space switching dialog measured with wrong height sometimes ([#6750](https://github.com/vector-im/element-android/issues/6750)) + - [App Layout] Fabs doesn't go off screen anymore ([#6765](https://github.com/vector-im/element-android/issues/6765)) + - [New Layout] Adds back navigation through spaces ([#6877](https://github.com/vector-im/element-android/issues/6877)) + - [App Layout] new room invites screen ([#6889](https://github.com/vector-im/element-android/issues/6889)) + - [App Layout] - Invites now show empty screen after you reject last invite ([#6876](https://github.com/vector-im/element-android/issues/6876)) + - [App Layout] - space switcher now has empty state ([#6754](https://github.com/vector-im/element-android/issues/6754)) + - [App Layout] - Improves Developer Mode Debug Button UX and adds it to New App Layout ([#6871](https://github.com/vector-im/element-android/issues/6871)) + - [New Layout] Changes space sheet to accordion-style with expandable subspaces ([#6907](https://github.com/vector-im/element-android/issues/6907)) + - [New Layout] Adds space invites ([#6924](https://github.com/vector-im/element-android/issues/6924)) + - [App Layout] fixed invites count badge bottom margin on a home screen ([#6947](https://github.com/vector-im/element-android/issues/6947)) + - [New Layout] Improves talkback accessibility ([#7016](https://github.com/vector-im/element-android/issues/7016)) + - [New Layout] Changes space icon in fab and in release notes screen ([#7039](https://github.com/vector-im/element-android/issues/7039)) + - [New Layout] Adds header to spaces bottom sheet ([#7040](https://github.com/vector-im/element-android/issues/7040)) + - [App Layout] New App Layout is enabled by default (Edit: has to be enabled in Labs) ([#6958](https://github.com/vector-im/element-android/issues/6958)) + - [App Layout] Obsolete settings are not shown when App Layout flag is enabled ([#6646](https://github.com/vector-im/element-android/issues/6646)) + - [Devices Management] Session overview screen ([#6961](https://github.com/vector-im/element-android/issues/6961)) + - [Devices Management] Refactor some code to improve testability ([#7043](https://github.com/vector-im/element-android/issues/7043)) + - [Device Manager] Current Session Section ([#6902](https://github.com/vector-im/element-android/issues/6902)) + - [Device Manager] Other Sessions Section ([#6945](https://github.com/vector-im/element-android/issues/6945)) + - [Device Manager] Render Security Recommendations ([#6964](https://github.com/vector-im/element-android/issues/6964)) + +Improved Documentation 📚 +------------------------ + - Clarify that setting up a FCM Rewrite Proxy is not necessary for use of the UnifiedPush FCM distributor. ([#6727](https://github.com/vector-im/element-android/issues/6727)) + +Other changes +------------- + - Increase sticker size ([#6982](https://github.com/vector-im/element-android/issues/6982)) + - Focus input field when editing homeserver address to speed up login and registration. ([#6926](https://github.com/vector-im/element-android/issues/6926)) + - Log basic Http information in production. ([#6925](https://github.com/vector-im/element-android/issues/6925)) + - Converts the vector module to a library with a parent vector-app application module ([#6407](https://github.com/vector-im/element-android/issues/6407)) + - Creates a dedicated strings module ([#3955](https://github.com/vector-im/element-android/issues/3955)) + - Remove FragmentModule and the Fragment factory. No need to Inject the constructor on your Fragment, just add @AndroidEntryPoint annotation and @Inject class members. ([#6894](https://github.com/vector-im/element-android/issues/6894)) + - Small refactor of UnifiedPushHelper ([#6936](https://github.com/vector-im/element-android/issues/6936)) + - CI: only run sonarqube task when token is known ([#7057](https://github.com/vector-im/element-android/issues/7057)) + + Changes in Element v1.4.34 (2022-08-23) ======================================= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52ccf47e6a..6e3c784dac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,42 @@ -# Contributing code to Matrix +# Contributing to Element Android + + + +* [Contributing code to Matrix](#contributing-code-to-matrix) +* [Android Studio settings](#android-studio-settings) + * [Template](#template) +* [Compilation](#compilation) +* [I want to help translating Element](#i-want-to-help-translating-element) +* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue) + * [Kotlin](#kotlin) + * [Changelog](#changelog) + * [Code quality](#code-quality) + * [Internal tool](#internal-tool) + * [ktlint](#ktlint) + * [lint](#lint) + * [Unit tests](#unit-tests) + * [Tests](#tests) + * [Internationalisation](#internationalisation) + * [Adding new string](#adding-new-string) + * [Plurals](#plurals) + * [Editing existing strings](#editing-existing-strings) + * [Removing existing strings](#removing-existing-strings) + * [Renaming string ids](#renaming-string-ids) + * [Reordering strings](#reordering-strings) + * [Accessibility](#accessibility) + * [Layout](#layout) + * [Authors](#authors) +* [Thanks](#thanks) + + + +## Contributing code to Matrix Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md Element Android support can be found in this room: [![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org). -# Specific rules for Matrix Android projects +The rest of the document contains specific rules for Matrix Android projects ## Android Studio settings @@ -120,17 +152,21 @@ You should consider adding Unit tests with your PR, and also integration tests ( Translations are handled using an external tool: [Weblate](https://translate.element.io/projects/element-android/) -As a general rule, please never edit or add or remove translations to the project in a Pull Request. It can lead to merge conflict if the translations are also modified in Weblate side. +**As a general rule, please never edit or add or remove translations to the project in a Pull Request**. It can lead to merge conflict if the translations are also modified in Weblate side. Pull Request containing change(s) on the translation files cannot be merged. #### Adding new string -When adding new string resources, please only add new entries in the file `value/strings.xml`. Translations will be added later by the community of translators using Weblate. +When adding new string resources, please only add new entries in the file `values/strings.xml` ([this file](./library/ui-strings/src/main/res/values/strings.xml)). Translations will be added later by the community of translators using Weblate. -The file `value/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings. +The file `values/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings. -New strings can be added anywhere in the file `value/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file. +New strings can be added anywhere in the file `values/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file. -Do not hesitate to use plurals when appropriate. +##### Plurals + +Please use `plurals` resources when appropriate, and note that some languages have specific rules for `plurals`, so even if the string will always be at the plural form for English, please always create a `plurals` resource. + +Specific plural forms can be found [here](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html). #### Editing existing strings @@ -150,6 +186,23 @@ And add `tools:ignore="UnusedResources"` to the string, to let lint ignore that The string will be removed during the next sync with Weblate. +#### Renaming string ids + +This is possible to rename ids of the String resources, but since translation files cannot be edited, add TODO in the main strings.xml file above the strings you want to rename. + +```xml + +Hello Matrix world! +``` + +The string id(s) will be renamed during the next Weblate sync. + +#### Reordering strings + +To group strings per feature, or for any other reasons, it is possible to reorder string resources, but only in the [main strings.xml file](./library/ui-strings/src/main/res/values/strings.xml). ). We do not mind about ordering in the translation files, and anyway this is forbidden to edit manually the translation files. + +It is also possible to add empty lines between string resources, and to add XML comments. Please note that the XML comment just above a String resource will also appear on Weblate and be visible to the translators. + ### Accessibility Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`. diff --git a/README.md b/README.md index 7acb5aa638..e351b64927 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,12 @@ If you would like to receive releases more quickly (bearing in mind that they ma ## Contributing -Please refer to [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects! +Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) if you want to contribute on Matrix Android projects! Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org). +Also [this documentation](./docs/_developer_onboarding.md) can hopefully help developers to start working on the project. + ## Triaging issues Issues are triaged by community members and the Android App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process). diff --git a/build.gradle b/build.gradle index 71875c49f1..d8de6dd55f 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ buildscript { classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' classpath "com.likethesalad.android:stem-plugin:2.2.2" - classpath 'org.owasp:dependency-check-gradle:7.1.2' + classpath 'org.owasp:dependency-check-gradle:7.2.0' classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3' @@ -45,7 +45,7 @@ plugins { id "io.gitlab.arturbosch.detekt" version "1.21.0" // Dependency Analysis - id 'com.autonomousapps.dependency-analysis' version "1.12.0" + id 'com.autonomousapps.dependency-analysis' version "1.13.1" } // https://github.com/jeremylong/DependencyCheck @@ -71,6 +71,14 @@ allprojects { groups.mavenCentral.group.each { includeGroup it } } } + // snapshots repository + maven { + url "https://oss.sonatype.org/content/repositories/snapshots" + content { + groups.snapshot.regex.each { includeGroupByRegex it } + groups.snapshot.group.each { includeGroup it } + } + } maven { url 'https://jitpack.io' content { diff --git a/changelog.d/3955.misc b/changelog.d/3955.misc deleted file mode 100644 index 4e8fbeb4d8..0000000000 --- a/changelog.d/3955.misc +++ /dev/null @@ -1 +0,0 @@ -Creates a dedicated strings module diff --git a/changelog.d/5525.wip b/changelog.d/5525.wip deleted file mode 100644 index 0d54c06b6a..0000000000 --- a/changelog.d/5525.wip +++ /dev/null @@ -1 +0,0 @@ -Create DM room only on first message - Create the DM and navigate to the new room after sending an event diff --git a/changelog.d/6407.misc b/changelog.d/6407.misc deleted file mode 100644 index 3f7a27fc01..0000000000 --- a/changelog.d/6407.misc +++ /dev/null @@ -1 +0,0 @@ -Converts the vector module to a library with a parent vector-app application module diff --git a/changelog.d/6565.wip b/changelog.d/6565.wip deleted file mode 100644 index 0e89c63e75..0000000000 --- a/changelog.d/6565.wip +++ /dev/null @@ -1 +0,0 @@ -[App Layout] Bottom navigation tabs are removed for new home screen diff --git a/changelog.d/6750.wip b/changelog.d/6750.wip deleted file mode 100644 index 2e18110c97..0000000000 --- a/changelog.d/6750.wip +++ /dev/null @@ -1 +0,0 @@ -[App Layout] fixed space switching dialog measured with wrong height sometimes diff --git a/changelog.d/6765.wip b/changelog.d/6765.wip deleted file mode 100644 index ccdc1c025f..0000000000 --- a/changelog.d/6765.wip +++ /dev/null @@ -1 +0,0 @@ -[App Layout] Fabs doesn't go off screen anymore diff --git a/changelog.d/6844.bugfix b/changelog.d/6844.bugfix deleted file mode 100644 index a2babaaa6d..0000000000 --- a/changelog.d/6844.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes /addToSpace and /joinSpace commands showing invalid syntax warnings diff --git a/changelog.d/6871.feature b/changelog.d/6871.feature deleted file mode 100644 index 313be1a602..0000000000 --- a/changelog.d/6871.feature +++ /dev/null @@ -1 +0,0 @@ -Improves Developer Mode Debug Button UX and adds it to New App Layout diff --git a/changelog.d/6877.wip b/changelog.d/6877.wip deleted file mode 100644 index d1e1c7c82d..0000000000 --- a/changelog.d/6877.wip +++ /dev/null @@ -1 +0,0 @@ -[New Layout] Adds back navigation through spaces diff --git a/changelog.d/6889.wip b/changelog.d/6889.wip deleted file mode 100644 index 067973aad9..0000000000 --- a/changelog.d/6889.wip +++ /dev/null @@ -1 +0,0 @@ -[App Layout] new room invites screen diff --git a/changelog.d/6894.misc b/changelog.d/6894.misc deleted file mode 100644 index abb1a69a71..0000000000 --- a/changelog.d/6894.misc +++ /dev/null @@ -1 +0,0 @@ -Remove FragmentModule and the Fragment factory. No need to Inject the constructor on your Fragment, just add @AndroidEntryPoint annotation and @Inject class members. diff --git a/changelog.d/6902.wip b/changelog.d/6902.wip deleted file mode 100644 index 8c982cc9ae..0000000000 --- a/changelog.d/6902.wip +++ /dev/null @@ -1 +0,0 @@ -[Device Manager] Current Session Section diff --git a/changelog.d/6907.wip b/changelog.d/6907.wip deleted file mode 100644 index a8d887c66b..0000000000 --- a/changelog.d/6907.wip +++ /dev/null @@ -1 +0,0 @@ -[New Layout] Changes space sheet to accordion-style with expandable subspaces diff --git a/changelog.d/6917.bugfix b/changelog.d/6917.bugfix deleted file mode 100644 index 7ddcc16d9a..0000000000 --- a/changelog.d/6917.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix long incremental sync. diff --git a/changelog.d/6924.wip b/changelog.d/6924.wip deleted file mode 100644 index 11ff4a1eb2..0000000000 --- a/changelog.d/6924.wip +++ /dev/null @@ -1 +0,0 @@ -[New Layout] Adds space invites diff --git a/changelog.d/6925.misc b/changelog.d/6925.misc deleted file mode 100644 index f494b76b56..0000000000 --- a/changelog.d/6925.misc +++ /dev/null @@ -1 +0,0 @@ -Log basic Http information in production. diff --git a/changelog.d/6926.misc b/changelog.d/6926.misc deleted file mode 100644 index dc1330d9fc..0000000000 --- a/changelog.d/6926.misc +++ /dev/null @@ -1 +0,0 @@ -Focus input field when editing homeserver address to speed up login and registration. \ No newline at end of file diff --git a/changelog.d/6929.misc b/changelog.d/6929.misc new file mode 100644 index 0000000000..d12167cfea --- /dev/null +++ b/changelog.d/6929.misc @@ -0,0 +1 @@ +Target API 12 and compile with Android SDK 32. diff --git a/changelog.d/6945.wip b/changelog.d/6945.wip deleted file mode 100644 index 6f5916a8c2..0000000000 --- a/changelog.d/6945.wip +++ /dev/null @@ -1 +0,0 @@ -[Device Manager] Other Sessions Section diff --git a/changelog.d/6947.wip b/changelog.d/6947.wip deleted file mode 100644 index 9a3e13cddb..0000000000 --- a/changelog.d/6947.wip +++ /dev/null @@ -1 +0,0 @@ -[App Layout] fixed invites count badge bottom margin on a home screen diff --git a/changelog.d/6958.feature b/changelog.d/6958.feature deleted file mode 100644 index b508ff19a9..0000000000 --- a/changelog.d/6958.feature +++ /dev/null @@ -1 +0,0 @@ -[App Layout] New App Layout is enabled by default diff --git a/changelog.d/6964.wip b/changelog.d/6964.wip deleted file mode 100644 index f96dfe41ed..0000000000 --- a/changelog.d/6964.wip +++ /dev/null @@ -1 +0,0 @@ -[Device Manager] Render Security Recommendations diff --git a/changelog.d/6967.bugfix b/changelog.d/6967.bugfix deleted file mode 100644 index e2a1f70532..0000000000 --- a/changelog.d/6967.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix low occurrence crashes. diff --git a/changelog.d/6969.bugfix b/changelog.d/6969.bugfix deleted file mode 100644 index 4f3a161b41..0000000000 --- a/changelog.d/6969.bugfix +++ /dev/null @@ -1 +0,0 @@ -FTUE - Fixes optional email registration step always being mandatory diff --git a/changelog.d/6978.bugfix b/changelog.d/6978.bugfix deleted file mode 100644 index 878730062b..0000000000 --- a/changelog.d/6978.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash when opening an unknown room diff --git a/changelog.d/6979.bugfix b/changelog.d/6979.bugfix deleted file mode 100644 index ee43e83e96..0000000000 --- a/changelog.d/6979.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash on PIN code settings screen. diff --git a/changelog.d/6982.bugfix b/changelog.d/6982.bugfix deleted file mode 100644 index baa75d9c15..0000000000 --- a/changelog.d/6982.bugfix +++ /dev/null @@ -1,2 +0,0 @@ -Fix autoplayed animated stickers -Increase sticker size diff --git a/changelog.d/7114.wip b/changelog.d/7114.wip new file mode 100644 index 0000000000..79ad705132 --- /dev/null +++ b/changelog.d/7114.wip @@ -0,0 +1 @@ +[Device management] Verify current session diff --git a/changelog.d/7126.doc b/changelog.d/7126.doc new file mode 100644 index 0000000000..9c69350a11 --- /dev/null +++ b/changelog.d/7126.doc @@ -0,0 +1 @@ +Draft onboarding documentation of the project at `./docs/_developer_onboarding.md` diff --git a/changelog.d/7126.misc b/changelog.d/7126.misc new file mode 100644 index 0000000000..a79d61f819 --- /dev/null +++ b/changelog.d/7126.misc @@ -0,0 +1 @@ +Add support to `/devtools` command. diff --git a/changelog.d/7143.wip b/changelog.d/7143.wip new file mode 100644 index 0000000000..588f7fb255 --- /dev/null +++ b/changelog.d/7143.wip @@ -0,0 +1 @@ +[Device management] Verify another session diff --git a/changelog.d/7159.misc b/changelog.d/7159.misc new file mode 100644 index 0000000000..76f5f45c40 --- /dev/null +++ b/changelog.d/7159.misc @@ -0,0 +1 @@ +Fix lint warning, and cleanup the code diff --git a/changelog.d/7170.wip b/changelog.d/7170.wip new file mode 100644 index 0000000000..f5b71a14f8 --- /dev/null +++ b/changelog.d/7170.wip @@ -0,0 +1 @@ +[Device Manager] Unverified and inactive sessions list diff --git a/changelog.d/7198.sdk b/changelog.d/7198.sdk new file mode 100644 index 0000000000..115b8d6113 --- /dev/null +++ b/changelog.d/7198.sdk @@ -0,0 +1 @@ +Allow the sync timeout to be configured (mainly useful for testing) diff --git a/changelog.d/7211.misc b/changelog.d/7211.misc new file mode 100644 index 0000000000..44abd3d59d --- /dev/null +++ b/changelog.d/7211.misc @@ -0,0 +1 @@ + CI: Prevent modification of translations by developer. diff --git a/coverage.gradle b/coverage.gradle index 716f9b7cc7..2c0af25368 100644 --- a/coverage.gradle +++ b/coverage.gradle @@ -81,11 +81,11 @@ task generateCoverageReport(type: JacocoReport) { task unitTestsWithCoverage(type: GradleBuild) { // the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage startParameter.projectProperties.coverage = [enableTestCoverage: false] - tasks = [':vector:testGplayDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest'] + tasks = ['testDebugUnitTest'] } task instrumentationTestsWithCoverage(type: GradleBuild) { startParameter.projectProperties.coverage = [enableTestCoverage: true] startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui' - tasks = [':vector-app:connectedGplayDebugAndroidTest', ':vector:connectedGplayDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest'] + tasks = [':vector-app:connectedGplayDebugAndroidTest', ':vector:connectedDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest'] } diff --git a/dependencies.gradle b/dependencies.gradle index e25e7b42cb..2e70304670 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,36 +1,35 @@ ext.versions = [ 'minSdk' : 21, - 'compileSdk' : 31, - 'targetSdk' : 31, + 'compileSdk' : 32, + 'targetSdk' : 32, 'sourceCompat' : JavaVersion.VERSION_11, 'targetCompat' : JavaVersion.VERSION_11, ] - -// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142 -// Please test carefully before upgrading again. -def gradle = "7.1.3" +def gradle = "7.2.2" // Ref: https://kotlinlang.org/releases.html -def kotlin = "1.6.21" +def kotlin = "1.7.10" def kotlinCoroutines = "1.6.4" -def dagger = "2.42" -def appDistribution = "16.0.0-beta03" +def dagger = "2.43.2" +def appDistribution = "16.0.0-beta04" def retrofit = "2.9.0" def arrow = "0.8.2" def markwon = "4.6.2" def moshi = "1.13.0" def lifecycle = "2.5.1" def flowBinding = "1.2.0" -def flipper = "0.162.0" +def flipper = "0.164.0" def epoxy = "4.6.2" def mavericks = "2.7.0" def glide = "4.13.2" def bigImageViewer = "1.8.1" def jjwt = "0.11.5" -def vanniktechEmoji = "0.15.0" +// Temporary version to unblock #6929. Once 0.16.0 is released we should use it, and revert +// the whole commit which set version 0.16.0-SNAPSHOT +def vanniktechEmoji = "0.16.0-SNAPSHOT" -def fragment = "1.5.2" +def fragment = "1.5.3" // Testing def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819 @@ -51,7 +50,7 @@ ext.libs = [ ], androidx : [ 'activity' : "androidx.activity:activity:1.5.1", - 'appCompat' : "androidx.appcompat:appcompat:1.4.2", + 'appCompat' : "androidx.appcompat:appcompat:1.5.1", 'biometric' : "androidx.biometric:biometric:1.1.0", 'core' : "androidx.core:core-ktx:1.8.0", 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1", @@ -86,7 +85,7 @@ ext.libs = [ 'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution", 'appdistribution' : "com.google.firebase:firebase-appdistribution:$appDistribution", // Phone number https://github.com/google/libphonenumber - 'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.12.54" + 'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.12.55" ], dagger : [ 'dagger' : "com.google.dagger:dagger:$dagger", diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index bcd737acc9..e44e0bc5c2 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -38,6 +38,13 @@ ext.groups = [ 'com.google.testing.platform', ] ], + snapshot: [ + regex: [ + ], + group: [ + 'com.vanniktech', + ] + ], mavenCentral: [ regex: [ ], @@ -69,8 +76,6 @@ ext.groups = [ 'com.gabrielittner.threetenbp', 'com.getkeepsafe.relinker', 'com.github.bumptech.glide', - 'com.github.filippudak', - 'com.github.filippudak.progresspieview', 'com.github.javaparser', 'com.github.piasy', 'com.github.shyiko.klob', @@ -120,7 +125,7 @@ ext.groups = [ 'com.sun.xml.bind.mvn', 'com.sun.xml.fastinfoset', 'com.thoughtworks.qdox', - 'com.vanniktech', + // 'com.vanniktech', 'commons-cli', 'commons-codec', 'commons-io', diff --git a/docs/_developer_onboarding.md b/docs/_developer_onboarding.md new file mode 100644 index 0000000000..2f414063e3 --- /dev/null +++ b/docs/_developer_onboarding.md @@ -0,0 +1,259 @@ +# Developer on boarding + + + +* [Introduction](#introduction) + * [Quick introduction to Matrix](#quick-introduction-to-matrix) + * [Matrix data](#matrix-data) + * [Room](#room) + * [Event](#event) + * [Sync](#sync) + * [Glossary about syncs](#glossary-about-syncs) + * [The Android project](#the-android-project) + * [Matrix SDK](#matrix-sdk) + * [Application](#application) + * [MvRx](#mvrx) + * [Behavior](#behavior) + * [Epoxy](#epoxy) + * [Other frameworks](#other-frameworks) + * [Push](#push) + * [Dependencies management](#dependencies-management) + * [Test](#test) + * [Other points](#other-points) + * [Logging](#logging) + * [Rageshake](#rageshake) + * [Tips](#tips) +* [Happy coding!](#happy-coding) + + + +## Introduction + +This doc is a quick introduction about the project and its architecture. + +It's aim is to help new developers to understand the overall project and where to start developing. + +Other useful documentation: +- all the docs in this folder! +- the [contributing doc](../CONTRIBUTING.md), that you should also read carefully. + +### Quick introduction to Matrix + +Matrix website: [matrix.org](https://matrix.org), [discover page](https://matrix.org/discover). +*Note*: Matrix.org is also hosting a homeserver ([.well-known file](https://matrix.org/.well-known/matrix/client)). +The reference homeserver (this is how Matrix servers are called) implementation is [Synapse](https://github.com/matrix-org/synapse/). But other implementations exist. The Matrix specification is here to ensure that any Matrix client, such as Element Android and its SDK can talk to any Matrix server. + +Have a quick look to the client-server API documentation: [Client-server documentation](https://spec.matrix.org/v1.3/client-server-api/). Other network API exist, the list is here: (https://spec.matrix.org/latest/) + +Matrix is an open source protocol. Change are possible and are tracked using [this GitHub repository](https://github.com/matrix-org/matrix-doc/). Changes to the protocol are called MSC: Matrix Spec Change. These are PullRequest to this project. + +Matrix object are Json data. Unstable prefixes must be used for Json keys when the MSC is not merged (i.e. accepted). + +#### Matrix data + +There are many object and data in the Matrix worlds. Let's focus on the most important and used, `Room` and `Event` + +##### Room + +`Room` is a place which contains ordered `Event`s. They are identified with their `room_id`. Nearly all the data are stored in rooms, and shared using homeserver to all the Room Member. + +*Note*: Spaces are also Rooms with a different `type`. + +##### Event + +`Events` are items of a Room, where data is embedded. + +There are 2 types of Room Event: + +- Regular Events: contain useful content for the user (message, image, etc.), but are not necessarily displayed as this in the timeline (reaction, message edition, call signaling). +- State Events: contain the state of the Room (name, topic, etc.). They have a non null value for the key `state_key`. + +Also all the Room Member details are in State Events: one State Event per member. In this case, the `state_key` is the matrixId (= userId). + +Important Fields of an Event: +- `event_id`: unique across the Matrix universe; +- `room_id`: the room the Event belongs to; +- `type`: describe what the Event contain, especially in the `content` section, and how the SDK should handle this Event; +- `content`: dynamic Event data; depends on the `type`. + +So we have a triple `event_id`, `type`, `state_key` which uniquely defines an Event. + +#### Sync + +The `Sync` is a way for the Matrix client to be up to date regarding the user data hosted by the server. All the Events are coming through the sync response. More details can be found here: [spec.matrix.org/v1.3/client-server-api/#syncing](https://spec.matrix.org/v1.3/client-server-api/#syncing) +When the application is in foreground, this is a looping request. We are using Https requests, which offer the advantage to be compatible with any homeserver. A sync token is used as request parameter, to let the server know what the client knows. +The `SyncThread` is responsible to manage the sync request loop. + +When the application is in background, a Push will trigger a sync request. + +##### Glossary about syncs + +- **initial sync**: a sync request without a token. This is the first request a client perform after login or after a clear cache. The server will include in the response all your rooms with the full state (all the room membership Event will not be present), with the latest messages for each room. We are in the process to replace this by version 3: sliding sync. All data are inserted to the Database (currently [Realm](https://www.mongodb.com/docs/realm/sdk/java/)). +- **incremental sync**: sync request with a token. +- **gappy sync**: sync request where all the new Events are not returned for one or several Rooms. Also called `limited sync`. It can be limited per Room. To get all the missing Events, a Room pagination API has to be called. +- **sync token**: `next_batch` value in the previous sync response. Will be provided as the `since` parameter for the next sync request. + +### The Android project + +The project should compile out of the box. + +The project is split into several modules. The main ones are: +For the app +- `vector-app`: application entry point; +- `vector`: legacy application, but now a library. In the process of being split into several modules; +- `vector-config`: this is where all the configuration of the application should occurs. Should because we are in the process of migrating all the configuration here; +- `library/ui-strings`: this is where all the string resources are stored. Please refer to [contributing doc](../CONTRIBUTING.md) to know how to make change on this module; +- `library/ui-styles`: this is where the Android styles are defined. + +For the SDK +- `matrix-sdk-android`: the main SDK module. The sources are in this project, but are also exported to [its own project](https://github.com/matrix-org/matrix-android-sdk2). All the PRs and issues related to the SDK take place in the Element Android project; +- `matrix-sdk-android-flow`: contains some wrapper to expose `Flow` to the application. + +### Matrix SDK + +SDK exposes `Services` to the client application. `Services` are public interface, and are defined in this parent package: `org.matrix.android.sdk.api`. Default implementation are internal to the SDK, in this parent package: `org.matrix.android.sdk.internal`. Note that you also have to declare the classes as `internal` when adding classes to the `org.matrix.android.sdk.internal` package. + +Interface allows us to replace the implementation for testing purpose. + +A generated documentation of the SDK is available [here](https://matrix-org.github.io/matrix-android-sdk2/). Updated after each release. Please ensure that the documentation (KDoc) of all the SDK Services is up to date, and is clear for a SDK user. +The SDK generated documentation also contains information about the entry points of the SDK. + +[Dagger](https://dagger.dev/) is used to inject all the dependencies to the SDK classes. + +SDK is exposing data as `LiveData`, but we are progressively migrating to `Flow`. Database is the source of truth. + +Example: +- Client send an Event using the `SendService`; +- At the end a `SendEvent` task is used; +- Retrofit API is used to send data to the server; +- Goes to the server, which returns only the `event_id`; +- The `Event` is coming back from the `sync` response with eventually extra added data. + +### Application + +This is the UI part of the project. + +There are two variants of the application: `Gplay` and `Fdroid`. + +The main difference is about using Firebase on `Gplay` variant, to have Push from Google Services. `FDroid` variant cannot contain closed source dependency. + +`Fdroid` is using background polling to lack the missing of Pushed. Now a solution using UnifiedPush has ben added to the project. See refer to [the dedicated documentation](./unifiedpush.md) for more details. + +#### MvRx + +[Maverick](https://airbnb.io/mavericks/#/README) (or MvRx) is an Android MVI framework that helps to develop Reactive application on Android. + +- Activity: holder for Fragment. See the parent [VectorBaseActivity](../vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt); +- Fragment: manage screen of the application. See the parent [VectorBaseFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt); +- BottomSheet: see the parent [VectorBaseBottomSheetDialogFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt); +- ViewModel: this is where the logic is placed. All our ViewModel has a `handle()` which takes action as parameter. See the parent [VectorViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt); +- VectorSharedActionViewModel: Specific ViewModel that can be used to communicate between Fragment(s) and the host Activity. See the parent [VectorSharedActionViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorSharedActionViewModel.kt); +- ViewState: this are `data class`, and this represent the state of the View. Has to be copied and set to be updated. Fragment will update the UI regarding the current state (`invalidate()` method). `Async` class from MvRx can be used in the ViewState, especially for asynchronous data loading. Nullability can also be used for optional data. ViewStates have to implement `MavericksState`; +- ViewEvents: useful when the ViewModel asks the View to trigger a specific action: navigation, show dialog, etc. See the parent [VectorViewEvents](../vector/src/main/java/im/vector/app/core/platform/VectorViewEvents.kt); +- ViewAction (`VectorViewModelAction`): useful when the UI (generally the Fragment) asks the ViewModel to do something. See the parent [VectorViewModelAction](../vector/src/main/java/im/vector/app/core/platform/VectorViewModelAction.kt); +- Controller: see the `Epoxy` section just below. + +##### Behavior + +Fragment asks the ViewModel to perform an action (coming from the user, but not necessarily. ViewModel can then talk to the SDK, updates the state once or several times. Fragment update the UI regarding the new state. + +When ViewModel is instantiated, it can subscribe using the SDK Services to get live state of the data. + +`invalidate()` has to be used by default, but it's possible to listen to specific member(s) of the `ViewState` using `onEach`. TODO Add an example. +`awaitState()` method + +#### Epoxy + +[Epoxy](https://github.com/airbnb/epoxy) is an Android library for building complex screens in a RecyclerView. Please read [the introduction](https://github.com/airbnb/epoxy#epoxy). + +- Controller declares items of the RecyclerView. Controller is injected in the Fragment. Controller extends `EpoxyController`, or one of its subclass, especially `TypedEpoxyController`; +- Fragment gives the state to the controller using `setData`; +- `buildModels` will be called by the framework; +- Controller will create ordered Items. + +Epoxy does the diffing, and handle many other thing for us, like handling item type, etc. + +See for instance the controller [AccountDataEpoxyController](../vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt)) for a simple example. + +Warning: do not use twice the same item `id` or it will crash. + +#### Other frameworks + +- Dependency injection is managed by [Dagger](https://dagger.dev/) (SDK) and [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) (App); +- [Retrofit](https://square.github.io/retrofit/) and [OkHttp3](https://square.github.io/okhttp/): network requests; +- [Moshi](https://github.com/square/moshi) is used to parse and serialize Json object; + +### Push + +Please see the dedicated documentation for more details. + +This is the classical scenario: + +- App receives a Push. Note: Push is ignored if app is in foreground; +- App asks the SDK to load Event data (fastlane mode). We have a change to get the data faster and display the notification faster; +- App asks the SDK to perform a sync request. + +### Dependencies management + +All the dependencies are declared in `build.gradle` files. But some versions are declared in [this dedicated file](../dependencies.gradle). + +When adding a new dependency, you will have to update the file [dependencies_groups.gradle](../dependencies_groups.gradle) to allow the dependency to be downloaded from the artifact repository. Sometimes sub-dependencies need to be added too, until the project can compile. + +[Dependabot](https://github.com/dependabot) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one. +dependencies_group, gradle files, Dependabot, etc. + +### Test + +Please refer to [this dedicated document](./ui-tests.md). + +TODO add link to the dedicated screenshot test documentation + +### Other points + +#### Logging + +**Important warning: ** NEVER log private user data, or use the flag `LOG_PRIVATE_DATA`. Be very careful when logging `data class`, all the content will be output! + +[Timber](https://github.com/JakeWharton/timber) is used to log data to logcat. We do not use directly the `Log` class. If possible please use a tag, as per + +````kotlin +Timber.tag(loggerTag.value).d("my log") +```` + +because automatic tag (= class name) will not be available on the release version. + +Also generally it is recommended to provide the `Throwable` to the Timber log functions. + +Last point, not that `Timber.v` function may have no effect on some devices. Prefer using `Timber.d` and up. + +#### Rageshake + +Rageshake is a feature to send bug report directly from the application. Just shake your phone and you will be prompted to send a bug report. + +Bug report can contain: +- a screenshot of the current application state +- the application logs from up to 15 application starts +- the logcat logs +- the key share history (crypto data) + +The data will be sent to an internal server, which is not publicly accessible. A GitHub issue will also be created to a private GitHub repository. + +Rageshake can be very useful to get logs from a release version of the application. + +### Tips + +- Element Android has a `developer mode` in the `Settings/Advanced settings`. Other useful options are available here; +- Show hidden Events can also help to debug feature. When developer mode is enabled, it is possible to view the source (= the Json content) of any Events; +- Type `/devtools` in a Room composer to access a developer menu. There are some other entry points. Developer mode has to be enabled; +- Hidden debug menu: when developer mode is enabled and on debug build, there are some extra screens that can be accessible using the green wheel. In those screens, it will be possible to toggle some feature flags; +- Using logcat, filtering with `onResume` can help you to understand what screen are currently displayed on your device. Searching for string displayed on the screen can also help to find the running code in the codebase. +- When this is possible, prefer using `sealed interface` instead of `sealed class`; +- When writing temporary code, using the string "DO NOT COMMIT" in a comment can help to avoid committing things by mistake. If committed and pushed, the CI will detect this String and will warn the user about it. + +## Happy coding! + +The team is here to support you, feel free to ask anything to other developers. + +Also please feel to update this documentation, if incomplete/wrong/obsolete/etc. + +**Thanks!** diff --git a/docs/danger.md b/docs/danger.md index afa3555469..34baa62e9e 100644 --- a/docs/danger.md +++ b/docs/danger.md @@ -28,6 +28,7 @@ Here are the checks that Danger does so far: - PR with change on layout should include screenshot in the description - PR which adds png file warn about the usage of vector drawables - non draft PR should have a reviewer +- files containing translations are not modified by developers ### Quality check diff --git a/docs/nightly_build.md b/docs/nightly_build.md index 7750e0466a..77cc676c7f 100644 --- a/docs/nightly_build.md +++ b/docs/nightly_build.md @@ -47,7 +47,7 @@ git checkout develop mv towncrier.toml towncrier.toml.bak sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml rm towncrier.toml.bak -yes n | towncrier --version nightly +yes n | towncrier build --version nightly ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES ``` diff --git a/docs/unifiedpush.md b/docs/unifiedpush.md index 2851644e66..9f44c6b2f9 100644 --- a/docs/unifiedpush.md +++ b/docs/unifiedpush.md @@ -18,7 +18,7 @@ The recently started UnifiedPush project is an Android protocol and library for The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application. -The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. +The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. A [FCM Rewrite Proxy](https://unifiedpush.org/developers/embedded_fcm/#fcm-rewrite-proxy) is not required for Element Android's implementation of the FCM distributor - it will work with an existing Matrix push provider, such as [Sygnal](https://github.com/matrix-org/sygnal). The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor. diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104340.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104340.txt new file mode 100644 index 0000000000..578549ce6c --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40104340.txt b/fastlane/metadata/android/de-DE/changelogs/40104340.txt new file mode 100644 index 0000000000..50b5647608 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Verschiedene Fehlerbehebungen und Stabilitätsverbesserungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/en-US/changelogs/40104360.txt b/fastlane/metadata/android/en-US/changelogs/40104360.txt new file mode 100644 index 0000000000..da03f28760 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40104360.txt @@ -0,0 +1,3 @@ +New App Layout can be enabled in the Labs settings. Please give it a try! +Fix issues about missing notification, and long incremental sync. +Full changelog: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/en-US/changelogs/40105000.txt b/fastlane/metadata/android/en-US/changelogs/40105000.txt new file mode 100644 index 0000000000..e86519e6e9 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40105000.txt @@ -0,0 +1,2 @@ +Main changes in this version: Deferred DM enabled by default. +Full changelog: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104340.txt b/fastlane/metadata/android/et/changelogs/40104340.txt new file mode 100644 index 0000000000..1df5ac4176 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104340.txt b/fastlane/metadata/android/fa/changelogs/40104340.txt new file mode 100644 index 0000000000..29efb95925 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104340.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104340.txt b/fastlane/metadata/android/fr-FR/changelogs/40104340.txt new file mode 100644 index 0000000000..fe61fd021c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104100.txt b/fastlane/metadata/android/hu-HU/changelogs/40104100.txt new file mode 100644 index 0000000000..97746bdcc6 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104100.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Görgetés a hangüzenetben. Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104110.txt b/fastlane/metadata/android/hu-HU/changelogs/40104110.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104110.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104120.txt b/fastlane/metadata/android/hu-HU/changelogs/40104120.txt new file mode 100644 index 0000000000..79df59cf5e --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104120.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Lehetővé teszi a felhasználók számára, hogy offline jelenjenek meg, és audio lejátszót ad hozzá a hangmellékletekhez. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104130.txt b/fastlane/metadata/android/hu-HU/changelogs/40104130.txt new file mode 100644 index 0000000000..79df59cf5e --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104130.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Lehetővé teszi a felhasználók számára, hogy offline jelenjenek meg, és audio lejátszót ad hozzá a hangmellékletekhez. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104140.txt b/fastlane/metadata/android/hu-HU/changelogs/40104140.txt new file mode 100644 index 0000000000..2ea8acda97 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104140.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: A figyelmen kívül hagyott felhasználók kezelésének javítása. Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104160.txt b/fastlane/metadata/android/hu-HU/changelogs/40104160.txt new file mode 100644 index 0000000000..d92018adb0 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104160.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: A titkosított üzenetek jobb kezelése. Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104180.txt b/fastlane/metadata/android/hu-HU/changelogs/40104180.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104180.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104190.txt b/fastlane/metadata/android/hu-HU/changelogs/40104190.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104190.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104200.txt b/fastlane/metadata/android/hu-HU/changelogs/40104200.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104200.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104220.txt b/fastlane/metadata/android/hu-HU/changelogs/40104220.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104230.txt b/fastlane/metadata/android/hu-HU/changelogs/40104230.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104240.txt b/fastlane/metadata/android/hu-HU/changelogs/40104240.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104250.txt b/fastlane/metadata/android/hu-HU/changelogs/40104250.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104260.txt b/fastlane/metadata/android/hu-HU/changelogs/40104260.txt new file mode 100644 index 0000000000..54d881323f --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104260.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: UnifiedPush használata, és lehetővé teszi a felhasználó számára, hogy FCM nélkül tolja. +Teljes változásnapló: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104270.txt b/fastlane/metadata/android/hu-HU/changelogs/40104270.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104270.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104280.txt b/fastlane/metadata/android/hu-HU/changelogs/40104280.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104280.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104300.txt b/fastlane/metadata/android/hu-HU/changelogs/40104300.txt new file mode 100644 index 0000000000..9882e09368 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Lehetővé teszi a továbbfejlesztett bejelentkezési és regisztrációs utakat. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104310.txt b/fastlane/metadata/android/hu-HU/changelogs/40104310.txt new file mode 100644 index 0000000000..9882e09368 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Lehetővé teszi a továbbfejlesztett bejelentkezési és regisztrációs utakat. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104320.txt b/fastlane/metadata/android/hu-HU/changelogs/40104320.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104320.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104340.txt b/fastlane/metadata/android/hu-HU/changelogs/40104340.txt new file mode 100644 index 0000000000..25772a8ea1 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások. +Teljes változásjegyzék: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104340.txt b/fastlane/metadata/android/id/changelogs/40104340.txt new file mode 100644 index 0000000000..1017951d47 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104340.txt b/fastlane/metadata/android/it-IT/changelogs/40104340.txt new file mode 100644 index 0000000000..556a6fc7ea --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/lt/full_description.txt b/fastlane/metadata/android/lt/full_description.txt new file mode 100644 index 0000000000..7189008456 --- /dev/null +++ b/fastlane/metadata/android/lt/full_description.txt @@ -0,0 +1,42 @@ +Element yra ir saugaus žinučių siuntimo, ir produktyvaus komandinio bendradarbiavimo programėlė, puikiai tinkanti grupiniams pokalbiams dirbant nuotoliniu būdu. Ši pokalbių programa naudoja visapusį šifravimą, kad užtikrintų galingas vaizdo konferencijas, dalijimąsi failais ir balso skambučius. + +Element funkcijos turi: +- Išplėstinės bendravimo internetu priemonės +- Visiškai užšifruotos žinutės, kad būtų galima saugiau bendrauti su įmone, net ir su nuotoliniais darbuotojais +- Decentralizuoti pokalbiai, pagrįsti atvirojo kodo sistema Matrix +- Saugus dalijimasis failais su šifruotais duomenimis valdant projektus +- Vaizdo pokalbiai su IP balso perdavimu ir ekrano bendrinimu +- Lengva integracija su mėgstamiausiomis internetinėmis bendradarbiavimo priemonėmis, projektų valdymo įrankiais, VoIP paslaugomis ir kitomis komandinių pokalbių programomis + +Element visiškai skiriasi nuo kitų žinučių siuntimo ir bendradarbiavimo programėlių. Ji veikia Matrix - atvirame tinkle, skirtame saugiam žinučių siuntimui ir decentralizuotam bendravimui. Jame galima savarankiškai talpinti duomenis ir žinutes savo serveryje, kad naudotojai galėtų maksimaliai valdyti ir kontroliuoti savo duomenis ir žinutes. + +Privatumas ir šifruotos žinutės +Element apsaugo jus nuo nepageidaujamų reklamų, duomenų gavybos ir uždarų sodų. Jis taip pat apsaugo visus jūsų duomenis, "vienas su vienu" vaizdo ir balso ryšį, naudodamas visapusį šifravimą ir kryžmiškai pasirašytą įrenginių patvirtinimą. + +Element suteikia galimybę kontroliuoti savo privatumą ir kartu saugiai bendrauti su visais, esančiais Matrix tinkle, arba kitais verslo bendradarbiavimo įrankiais integruojantis su tokiomis programėlėmis kaip Slack. + +Element gali būti savarankiškai talpinamas +Kad galėtumėte geriau kontroliuoti savo slaptus duomenis ir pokalbius, Element gali būti savarankiškai talpinamas arba galite pasirinkti bet kurį Matrix pagrindu veikiantį serverį - atvirojo kodo decentralizuoto bendravimo standartu. Element suteikia privatumą, saugumo atititikimą ir integracijos lankstumą. + +Jūsų duomenys priklauso jums +Jūs nusprendžiate, kur laikyti savo duomenis ir žinutes. Be duomenų gavybos ar trečiųjų šalių prieigos rizikos. + +Element suteikia jums kontrolę įvairiais būdais: +1. Gaukite nemokamą paskyrą viešajame serveryje matrix.org, kurį talpina Matrix kūrėjai, arba rinkitės iš tūkstančių viešųjų serverių, kurių talpinimą teikia savanoriai +2. Savarankiškai talpinkite savo paskyrą, naudodami serverį savo IT infrastruktūroje +3. Užsisakykite paskyrą nuosavame serveryje tiesiog užsisakydami "Element Matrix Services" talpinimo paslaugą + +Atviras žinučių siuntimas ir bendradarbiavimas +Galite bendrauti su bet kuriuo Matrix tinklo nariu, nesvarbu, ar jis naudojasi Element, kita Matrix programėle, ar net jei naudoja kitą žinučių siuntimo programėlę. + +Super saugus +Tikras visapusis šifravimas (žinutes gali iššifruoti tik pokalbio dalyviai) ir kryžminiu parašu patvirtintas įrenginių patvirtinimas. + +Pilnas bendravimas ir integracija +Žinučių siuntimas, balso ir vaizdo skambučiai, failų ir ekrano bendrinimas ir daugybė integracijų, robotų ir valdiklių. Kurkite kambarius, bendruomenes, palaikykite ryšį ir atlikite darbus. + +Tęskite darbą ten, kur baigėte +Palaikykite ryšį, kad ir kur būtumėte, naudodami visiškai sinchronizuotą žinučių istoriją visuose įrenginiuose ir internete adresu https://app.element.io + +Atviras kodas +Element Android yra atvirojo kodo projektas, kurį talpina GitHub. Praneškite apie klaidas ir (arba) prisidėkite prie jo kūrimo adresu https://github.com/vector-im/element-android diff --git a/fastlane/metadata/android/lt/short_description.txt b/fastlane/metadata/android/lt/short_description.txt new file mode 100644 index 0000000000..600e76b35d --- /dev/null +++ b/fastlane/metadata/android/lt/short_description.txt @@ -0,0 +1 @@ +Grupiniai pokalbiai - šifruotos žinutės ir vaizdo skambučiai diff --git a/fastlane/metadata/android/lt/title.txt b/fastlane/metadata/android/lt/title.txt new file mode 100644 index 0000000000..d911c34bb2 --- /dev/null +++ b/fastlane/metadata/android/lt/title.txt @@ -0,0 +1 @@ +Element - Saugūs pokalbiai diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104180.txt b/fastlane/metadata/android/nl-NL/changelogs/40104180.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104180.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104190.txt b/fastlane/metadata/android/nl-NL/changelogs/40104190.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104190.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104200.txt b/fastlane/metadata/android/nl-NL/changelogs/40104200.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104200.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104220.txt b/fastlane/metadata/android/nl-NL/changelogs/40104220.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104220.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104230.txt b/fastlane/metadata/android/nl-NL/changelogs/40104230.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104230.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104240.txt b/fastlane/metadata/android/nl-NL/changelogs/40104240.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104240.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104250.txt b/fastlane/metadata/android/nl-NL/changelogs/40104250.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104250.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104270.txt b/fastlane/metadata/android/nl-NL/changelogs/40104270.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104270.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104280.txt b/fastlane/metadata/android/nl-NL/changelogs/40104280.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104280.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104320.txt b/fastlane/metadata/android/nl-NL/changelogs/40104320.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104320.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/nl-NL/changelogs/40104340.txt b/fastlane/metadata/android/nl-NL/changelogs/40104340.txt new file mode 100644 index 0000000000..48796d85bc --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen. +Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104340.txt b/fastlane/metadata/android/pl-PL/changelogs/40104340.txt new file mode 100644 index 0000000000..e175a61725 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Rozmaite poprawki błędów i usprawnienia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104340.txt b/fastlane/metadata/android/pt-BR/changelogs/40104340.txt new file mode 100644 index 0000000000..6e11e92579 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104340.txt b/fastlane/metadata/android/sk/changelogs/40104340.txt new file mode 100644 index 0000000000..50670f18c2 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40104340.txt b/fastlane/metadata/android/uk/changelogs/40104340.txt new file mode 100644 index 0000000000..9664c615c1 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104340.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Перелік усіх змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104340.txt b/fastlane/metadata/android/zh-TW/changelogs/40104340.txt new file mode 100644 index 0000000000..4bcca9a0b8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104340.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/gradle.properties b/gradle.properties index 2af9214ed5..0e561faa8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,6 +12,7 @@ org.gradle.jvmargs=-Xmx4g -Xms512M -XX:MaxPermSize=2048m -XX:MaxMetaspaceSize=1g org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.vfs.watch=true +org.gradle.caching=true # Android Settings android.enableJetifier=true diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt index 764cf8419a..98398760d1 100644 --- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt +++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt @@ -17,7 +17,6 @@ package im.vector.lib.attachmentviewer -import android.annotation.SuppressLint import android.graphics.Color import android.os.Build import android.os.Bundle @@ -136,7 +135,6 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi } } - @Suppress("DEPRECATION") private fun setDecorViewFullScreen() { // This is important for the dispatchTouchEvent, if not we must correct // the touch coordinates @@ -144,22 +142,20 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION window.setDecorFitsSystemWindows(false) // New API instead of SYSTEM_UI_FLAG_IMMERSIVE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } else { - @SuppressLint("WrongConstant") - window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE - } + window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // New API instead of FLAG_TRANSLUCENT_STATUS window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar) // new API instead of FLAG_TRANSLUCENT_NAVIGATION window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar) } else { + @Suppress("DEPRECATION") window.decorView.systemUiVisibility = ( View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE) + @Suppress("DEPRECATION") window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + @Suppress("DEPRECATION") window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) } } @@ -344,7 +340,6 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi ?.handleCommand(commands) } - @Suppress("DEPRECATION") private fun hideSystemUI() { systemUiVisibility = false // Enables regular immersive mode. @@ -356,17 +351,13 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi // new API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars()) // New API instead of SYSTEM_UI_FLAG_IMMERSIVE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } else { - @SuppressLint("WrongConstant") - window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE - } + window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // New API instead of FLAG_TRANSLUCENT_STATUS window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar) // New API instead of FLAG_TRANSLUCENT_NAVIGATION window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar) } else { + @Suppress("DEPRECATION") window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE // Set the content to appear under the system bars so that the // content doesn't resize when the system bars hide and show. @@ -381,13 +372,13 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi // Shows the system bars by removing all the flags // except for the ones that make the content appear under the system bars. - @Suppress("DEPRECATION") private fun showSystemUI() { systemUiVisibility = true if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION window.setDecorFitsSystemWindows(false) } else { + @Suppress("DEPRECATION") window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle index ad472b0b54..fcad3f1087 100644 --- a/library/jsonviewer/build.gradle +++ b/library/jsonviewer/build.gradle @@ -55,8 +55,9 @@ dependencies { implementation libs.airbnb.mavericks // Span utils - implementation 'me.gujun.android:span:1.7' - + implementation('me.gujun.android:span:1.7') { + exclude group: 'com.android.support', module: 'support-annotations' + } implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid diff --git a/library/ui-strings/build.gradle b/library/ui-strings/build.gradle index 860fc3c980..6a31f24c9b 100644 --- a/library/ui-strings/build.gradle +++ b/library/ui-strings/build.gradle @@ -20,3 +20,7 @@ android { jvmTarget = "11" } } + +tasks.withType( com.likethesalad.android.templates.common.tasks.BaseTask) { + it.outputs.cacheIf { true } +} diff --git a/library/ui-strings/src/main/res/values-ar/strings.xml b/library/ui-strings/src/main/res/values-ar/strings.xml index 073f961cb6..70b9a33ab5 100644 --- a/library/ui-strings/src/main/res/values-ar/strings.xml +++ b/library/ui-strings/src/main/res/values-ar/strings.xml @@ -320,7 +320,7 @@ السمة خطأ في فكّ التعمية اسم الجهاز - معرّف الجهاز + معرّف الجهاز مفتاح الجهاز صدّر مفاتيح الغرفة صدّر المفاتيح إلى ملف محلي diff --git a/library/ui-strings/src/main/res/values-bg/strings.xml b/library/ui-strings/src/main/res/values-bg/strings.xml index b29823040f..d3e9e599bc 100644 --- a/library/ui-strings/src/main/res/values-bg/strings.xml +++ b/library/ui-strings/src/main/res/values-bg/strings.xml @@ -396,7 +396,7 @@ Тема Грешка при разшифроване Публично име - Сесийно ID + Сесийно ID Ключ на устройство Експортирай E2E ключове за стая Експортиране на ключове за стая diff --git a/library/ui-strings/src/main/res/values-bn-rBD/strings.xml b/library/ui-strings/src/main/res/values-bn-rBD/strings.xml index 2f068f1bf8..7897da934e 100644 --- a/library/ui-strings/src/main/res/values-bn-rBD/strings.xml +++ b/library/ui-strings/src/main/res/values-bn-rBD/strings.xml @@ -789,7 +789,7 @@ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন সেশানের কুঞ্জি - আইডি + আইডি সর্বজনীন নাম ডিক্রিপশন সমস্যা থিম diff --git a/library/ui-strings/src/main/res/values-bn-rIN/strings.xml b/library/ui-strings/src/main/res/values-bn-rIN/strings.xml index 828bc3bd34..56bde36977 100644 --- a/library/ui-strings/src/main/res/values-bn-rIN/strings.xml +++ b/library/ui-strings/src/main/res/values-bn-rIN/strings.xml @@ -693,7 +693,7 @@ ডিক্রিপশন সমস্যা সর্বজনীন নাম - আইডি + আইডি সেশানের কুঞ্জি শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন diff --git a/library/ui-strings/src/main/res/values-ca/strings.xml b/library/ui-strings/src/main/res/values-ca/strings.xml index 0c61cdf6c6..863fa13fbb 100644 --- a/library/ui-strings/src/main/res/values-ca/strings.xml +++ b/library/ui-strings/src/main/res/values-ca/strings.xml @@ -448,7 +448,7 @@ Tema Error al desxifrar Nom públic - ID de sessió + ID de sessió Clau de sessió Exporta les claus de la sala E2E Exporta les claus de la sala @@ -1470,7 +1470,7 @@ %d sessió activa %d sessions actives - Aquesta sessió és de confiança per a xats segurs ja que l\'has verificada tu: + Aquesta sessió és de confiança per a missatges segurs ja que l\'has verificada tu: Desconnecta aquesta sessió Gestió de sessions Veure totes les sessions @@ -1844,7 +1844,7 @@ Altres idiomes disponibles Idioma actual Motiu de l\'eliminació - Aquesta sessió és de confiança per a xats segurs ja que %1$s (%2$s) l\'ha verificat: + Aquesta sessió és de confiança per a missatges segurs ja que %1$s (%2$s) l\'ha verificat: Obtenint clau de corba No s\'ha pogut crear el xat. Comprova els usuaris que vols convidar i torna-ho a provar. Verifica manualment mitjançant text @@ -2225,7 +2225,7 @@ Tria on es desen les teves converses, et dona control i independència. Connectat a través de Matrix. Comunicació segura i independent que t\'ofereix el mateix nivell de privadesa que una conversa cara a cara a casa teva. Missatgeria pel teu equip. - Missatgeria segura. + Missatges segurs. Ets propietari de les teves converses. Tu tens el control. Trucada finalitzada • %1$s @@ -2602,8 +2602,8 @@ Tots els xats Preferències de disseny Explora sales - Per estar més segur, verifica les teves sessions i tanca qualsevol sessió que no reconeguis o ja no utilitzis. - Altres sessions + Per estar més segur, verifica les teves sessions i tanca qualsevol sessió que no reconeguis o ja no utilitzis. + Altres sessions Sessions Obre la llista d\'espais Crea un nou xat o sala @@ -2619,4 +2619,59 @@ Mostra totes les sessions (V2, WIP) Crea sala Inicia xat - + Verificada · Última activitat %1$s + No verificada · Última activitat %1$s + Veure-ho tot (%1$d) + Veure detalls + Verifica sessió + Sessió no verificada + Sessió verificada + Tipus de dispositiu desconegut + Ordinador + Web + Mòbil + Aquesta sala no s\'ha trobat. +\nTorna-ho a provar més tard.%s + Invitacions + ${app_name} +\nHola, %s. + Nova visualització! + Prova-ho + Entra a espais + L\'aplicació de xats segurs tot en un. Per a equips, amics i organitzacions. Crea un xat o uneix-te a una sala existent per començar. + + Pensa en tancar sessió de les sessions antigues (%1$d dia o més) que ja no utilitzis. + Pensa en tancar sessió de les sessions antigues (%1$d dies o més) que ja no utilitzis. + + Prem la part superior dreta per veure l\'opció d\'enviar comentaris. + Envia comentaris + Aquí es mostraran els teus missatges no llegits, quan en tinguis. + Sense novetats. + Verifica les sessions o tanca\'n la sessió si no estan verificades. + Per simplificar ${app_name}, les pestanyes ara son opcionals. Gestiona-les mitjançant el menú de la part superior dreta. + %s +\nsembla una mica buit. + Sessions inactives + Sessions no verificades + Millora la seguretat del teu compte seguint aquestes recomanacions. + Recomanacions de seguretat + + Actiu fa %1$d dia (%2$s) + Actiu fa més de %1$d dies (%2$s) + + Aquí és on apareixeran les teves sol·licituds i invitacions. + Res de nou. + Accedeix als teus espais (part inferior dreta) més ràpid i fàcilment. + Els espais són una nova manera d\'agrupar sales i gent. Afegeix una sala o crea\'n una de nova mitjançant el botó de la part inferior dreta. + Els espais són una nova manera d\'agrupar sales i gent. Crea\'n un per començar. + Cap espai, encara. + Amaga els continguts de %s + Mostra el contingut de %s + Canvia espai + Verifica les teves sessions per obtenir missatges segurs millorats o tanca les sessions que no reconeguis o ja no utilitzis. + No llest per a missatges segurs + Llest per a missatges segurs + Aquesta sessió està llesta per a missatges segurs. + La teva sessió actual està llesta per a missatges segurs. + Verifica la teva sessió actual obtenir missatges segurs millorats. + \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 200480ffa2..79f8311159 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -635,7 +635,7 @@ Motiv vzhledu Chyba dešifrování Veřejné jméno - ID relace + ID relace Klíč relace Export E2E klíčů místností Export klíčů místností @@ -2651,8 +2651,8 @@ Otevřít nastavení Všechny konverzace Zobrazit všechny relace (V2, WIP) - V zájmu co nejlepšího zabezpečení ověřujte své relace a odhlašujte se ze všech relací, které již nepoznáváte nebo nepoužíváte. - Ostatní relace + V zájmu co nejlepšího zabezpečení ověřujte své relace a odhlašujte se ze všech relací, které již nepoznáváte nebo nepoužíváte. + Ostatní relace Relace Seznam otevřených prostorů Vytvořit novou konverzaci nebo místnost @@ -2669,4 +2669,55 @@ Prozkoumat místnosti Vytvořit místnost Zahájit konverzaci + Neověřeno · Poslední aktivita %1$s + Ověřeno · Poslední aktivita %1$s + Zobrazit všechny (%1$d) + Zobrazit podrobnosti + Ověřit relaci + Neověřená relace + Ověřená relace + Neznámý typ zařízení + Desktop + Web + Mobil + Je nám líto, tato místnost nebyla nalezena. +\nZkuste to prosím později.%s + Pozvánky + Vyzkoušejte to + Klepnutím vpravo nahoře zobrazíte možnost zpětné vazby. + Poskytněte zpětnou vazbu + Přístup k vašim prostorům (vpravo dole) je rychlejší a snazší než kdykoli předtím. + Přístup do prostorů + Pro zjednodušení aplikace ${app_name} jsou nyní karty nepovinné. Spravujte je pomocí nabídky vpravo nahoře. + Vítejte v novém zobrazení! + Zde se zobrazí nepřečtené zprávy, pokud nějaké máte. + Nic k nahlášení. + Univerzální zabezpečená chatovací aplikace pro týmy, přátele a organizace. Vytvořte si chat nebo se připojte k existující místnosti a začněte. + Vítejte v aplikaci ${app_name}, +\n%s. + Prostory představují nový způsob seskupování místností a osob. Pomocí tlačítka vpravo dole můžete přidat stávající místnost nebo vytvořit novou. + %s +\nvypadá trochu prázdně. + + Zvažte odhlášení ze starých relací (%1$d den nebo více), které již nepoužíváte. + Zvažte odhlášení ze starých relací (%1$d dny nebo více), které již nepoužíváte. + Zvažte odhlášení ze starých relací (%1$d dnů nebo více), které již nepoužíváte. + + Neaktivní relace + Ověřte nebo se odhlaste z neověřených relací. + Neověřené relace + Zlepšete zabezpečení svého účtu dodržováním těchto doporučení. + Bezpečnostní doporučení + + Neaktivní po dobu %1$d+ dne (%2$s) + Neaktivní po dobu %1$d+ dnů (%2$s) + Neaktivní po dobu %1$d+ dnů (%2$s) + + Zde se budou nacházet vaše nové žádosti a pozvánky. + Nic nového. + Prostory představují nový způsob seskupování místností a osob. Vytvořte si prostor a začněte. + Zatím žádné prostory. + Sbalit podprostory %s + Rozbalit podprostory %s + Změnit prostor diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 527b21ad56..e01fc898a3 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -20,7 +20,7 @@ %s hat einen Sprachanruf getätigt. %s hat den Anruf angenommen. %s hat den Anruf beendet. - %1$s hat den zukünftigen Chatverlauf sichtbar gemacht für %2$s + %1$s hat den zukünftigen Nachrichtenverlauf sichtbar gemacht für %2$s alle Mitglieder, ab Einladung. alle Mitglieder, ab Beitritt. alle Mitglieder. @@ -265,11 +265,11 @@ Räume Logdateien übermitteln Absturzberichte übermitteln - Screenshot übermitteln + Bildschirmfoto übermitteln Problem melden Bitte beschreibe das Problem. Was hast du genau gemacht\? Was sollte passieren\? Was ist tatsächlich passiert\? Problembeschreibung - Um Probleme diagnostizieren zu können, werden Protokolle des Clients zusammen mit dem Fehlerbericht übermittelt. Dieser Fehlerbericht wird, wie die Protokolle und der Screenshot, nicht öffentlich sichtbar sein. Wenn du nur den oben eingegebenen Text senden möchtest, die nachfolgenden Haken entsprechend entfernen: + Um Probleme diagnostizieren zu können, werden Protokolle des Clients zusammen mit dem Fehlerbericht übermittelt. Dieser Fehlerbericht wird, wie die Protokolle und das Bildschirmfoto, nicht öffentlich sichtbar sein. Wenn du nur den oben eingegebenen Text senden möchtest, die nachfolgenden Haken entsprechend entfernen: Du scheinst dein Telefon frustriert zu schütteln. Möchtest du das Fenster zum Senden eines Fehlerberichts öffnen\? Dein Fehlerbericht wurde erfolgreich übermittelt Der Fehlerbericht konnte nicht übermittelt werden (%s) @@ -418,7 +418,7 @@ Als Hauptadresse aufheben Entschlüsselungsfehler Öffentlicher Name - Sitzungs-ID + Sitzungs-ID Sitzungsschlüssel Ende-zu-Ende-Raumschlüssel exportieren Raumschlüssel exportieren @@ -834,9 +834,9 @@ \nSitzungsname: %1$s \nZuletzt gesehen: %2$s \nWenn du nicht mit einer anderen Sitzung angemeldet bist, ignoriere diese Anfrage. - Eine unverifizierte Sitzung fordert Verschlüsselungs-Schlüssel an. -\nSitzungsname: %1$s -\nZuletzt gesehen: %2$s + Eine nicht verifizierte Sitzung fordert Verschlüsselungs-Schlüssel an. +\nSitzungsname: %1$s +\nZuletzt gesehen: %2$s \nWenn du nicht eine andere Sitzung angemeldet hast, ignoriere diese Anfrage. Teilen Ignorieren @@ -908,7 +908,7 @@ (bearbeitet) Nachrichtenbearbeitung Keine Änderungen gefunden - Gespräche filtern… + Konversationen filtern … Sende eine neue Direktnachricht Das Raumverzeichnis anzeigen Link in die Zwischenablage kopiert @@ -994,7 +994,7 @@ Eine Textnachricht wurde an %s gesendet. Bitte gib den Verifizierungscode ein, den sie enthält. Aktiviere ausführliche Logs. Ausführliche Logs werden der Entwicklung der App dadurch helfen, dass mehr Informationen übertragen werden, wenn du einen Fehlerbericht sendest. Auch wenn dies aktiviert ist, werden keine Nachrichteninhalte oder andere privaten Daten aufgezeichnet. - Bitte erneut versuchen, nachdem du die Nutzungsbedingungen deines Homeservers akzeptiert hast. + Bitte erneut versuchen, nachdem du die Nutzungsbedingungen deines Heimservers akzeptiert hast. Bei Benutzung könnten Cookies gesetzt werden und es könnten Daten mit %s geteilt werden: Bei Benutzung könnten Daten mit %s geteilt werden: Optionen zum Finden werden erscheinen, sobald du eine Telefonnummer hinzugefügt hast. @@ -1409,8 +1409,8 @@ nutze deinen Schlüsselbackup-Wiederherstellungsschlüssel Wenn du dein Schlüsselbackup-Passwort nicht weißt, kannst du %s. Schlüsselbackup-Wiederherstellungsschlüssel - Screenshots innerhalb der Anwendung verhindern - Das Aktivieren dieser Einstellung setzt das FLAG_SECURE in allen Aktivitäten. Starte die Anwendung neu, damit die Änderung wirksam wird. + Bildschirmfotos der Anwendung verhindern + Das Aktivieren dieser Einstellung setzt FLAG_SECURE in allen Aktivitäten. Starte die Anwendung neu, damit die Änderung wirksam wird. Neues Benutzerpasswort festlegen… Nutze die neueste Version von ${app_name} auf deinen anderen Geräten, ${app_name} Web, ${app_name} Desktop, ${app_name} iOS, ${app_name} für Android oder einen anderen cross-signing-fähigen Matrix-Client ${app_name} Web @@ -1426,7 +1426,7 @@ Wähle deinen Wiederherstellungsschlüssel, gib ihn ein oder füge ihn aus der Zwischenablage ein Konnte nicht auf gesicherten Speicher zugreifen Unverschlüsselt - Verschlüsselt von einem unbekannten Gerät + Verschlüsselt von einem nicht verifiziertem Gerät Überprüfe, wo du angemeldet bist Verifiziere alle deine Sitzungen, um sicherzustellen, dass dein Konto und deine Nachrichten sicher sind Bestätige neue Anmeldung zu deinem Konto: %1$s @@ -1461,7 +1461,7 @@ Ablehnen Erfolg Echtzeitverbindung konnte nicht hergestellt werden. -\nBitte den Administrator deines Homeservers, einen TURN-Server zu konfigurieren, dass Anrufe zuverlässig funktionieren. +\nBitte den Administrator deines Heimservers, einen TURN-Server zu konfigurieren, damit Anrufe zuverlässig funktionieren. Audiogerät auswählen Telefon Lautsprecher @@ -1744,13 +1744,13 @@ Direktnachricht Verlauf der Anfragen von Schlüsselfreigaben senden Keine weiteren Ergebnisse - Starte die Diskussion + Beginne ein Gespräch Autorisieren Meine Zustimmung widerrufen Du hast zugestimmt E-Mails und Telefonnummern an diesen Identitätsserver zu senden, um von anderen Nutzern entdeckt zu werden. E-Mails und Telefonnummern senden Vorschläge - Bekannte Nutzer + Bekannte Personen QR-Code Hinzufügen via QR-Code Gib die Erlaubnis, um auf die Kamera zu zugreifen. @@ -1794,7 +1794,7 @@ Manche Zeichen sind nicht zulässig Bitte gib eine Raumadresse an Diese Adresse ist bereits vergeben - Aktivieren, wenn der Raum nur von Mitgliedern deines Homeservers zur internen Kommunikation verwendet wird. Das kann später nicht mehr geändert werden. + Aktivieren, wenn der Raum nur von Mitgliedern deines Heimservers zur internen Kommunikation verwendet wird. Das kann später nicht mehr geändert werden. Begrenze Zugang zu diesem Raum (für immer!) auf Mitglieder von %s %1$d von %2$d Keine Vorschau für diesen Raum verfügbar. Willst du direkt beitreten\? @@ -1845,7 +1845,7 @@ Einmalanmeldung Anmelden mit %s Registrieren mit %s - Mit %s weitermachen + Weiter mit %s Knopf zum Nachrichteneditor hinzufügen, der die Emoji-Tastatur öffnet Emoji-Tastatur anzeigen Nutze /confetti oder sende Nachrichten mit ❄️ oder 🎉 @@ -2188,7 +2188,7 @@ Hilfreiche Informationen zur Fehlersuche anzeigen Debug-Info anzeigen Das schaut nicht nach einer gültigen E-Mail-Adresse aus - Nach Name, ID oder E-Mail suchen + Mittels Name, ID oder E-Mail-Adresse suchen Neuen Space erstellen Zugriff Wer hat Zugriff\? @@ -2587,8 +2587,8 @@ Personen Schreibe deine erste Nachricht, um %s zur Konversation einzuladen Alle Sitzungen anzeigen (V2, in Arbeit) - Für bestmögliche Sicherheit verifiziere deine Sitzungen und melde dich von allen ab, die du nicht erkennst oder nutzt. - Andere Sitzungen + Für bestmögliche Sicherheit verifiziere deine Sitzungen und melde dich von allen ab, die du nicht erkennst oder nutzt. + Andere Sitzungen Sitzungen Space-Liste öffnen Beginne ein Gespräch oder erstelle einen Raum @@ -2614,4 +2614,29 @@ Kontakt aufnehmen Element Matrix Services (EMS) ist ein robuster und zuverlässiger Hosting-Dienst für schnelle und sichere Echtzeitkommunikation. Erfahre mehr unter element.io/ems Willst du deinen eigenen Server betreiben\? - \ No newline at end of file + Web + Mobil + Entschuldigung, dieser Raum wurde nicht gefunden. +\nBitte versuche es später erneut.%s + Einladungen + Nicht verifiziert · Letzte Aktivität %1$s + Nicht verifizierte Sitzung + Nicht verifizierte Sitzung + Verbessere deine Kontosicherheit, indem du diese Empfehlungen beherzigst. + Sicherheitsempfehlungen + + Inaktiv seit %1$d+ Tag (%2$s) + Inaktiv seit %1$d+ Tagen (%2$s) + + Verifiziert · Letzte Aktivität %1$s + Verifizierte Sitzung + Unbekannter Gerätetyp + Nichts Neues. + Spaces sind eine neue Art, Räume und Personen zu organisieren. Erstelle einen Space, um zu beginnen. + Noch keine Spaces. + Hier werden deine ungelesenen Nachrichten erscheinen, wenn du welche hast. + Es gibt nichts Neues. + Alle Unterhaltungen + Space wechseln + Unterhaltung beginnen + diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 092a01bff4..f4973f4b95 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -172,7 +172,7 @@ Θέμα Σφάλμα αποκρυπτογράφησης Όνομα συσκευής - Αναγνωριστικό συσκευής + Αναγνωριστικό συσκευής Εξαγωγή Εισαγωγή Επιλέξτε ένα ευρετήριο δωματίων diff --git a/library/ui-strings/src/main/res/values-eo/strings.xml b/library/ui-strings/src/main/res/values-eo/strings.xml index 7e1925f708..f536ca00f9 100644 --- a/library/ui-strings/src/main/res/values-eo/strings.xml +++ b/library/ui-strings/src/main/res/values-eo/strings.xml @@ -1084,7 +1084,7 @@ Elporti ŝlosilojn de ĉambroj Elporti tutvoje ĉifrajn ŝlosilojn de ĉambroj Ŝlosilo de salutaĵo - Identigilo de salutaĵo + Identigilo de salutaĵo Publika nomo Eraris malĉifrado Haŭto diff --git a/library/ui-strings/src/main/res/values-es-rMX/strings.xml b/library/ui-strings/src/main/res/values-es-rMX/strings.xml index 0b38fa6a19..c82f9aff61 100644 --- a/library/ui-strings/src/main/res/values-es-rMX/strings.xml +++ b/library/ui-strings/src/main/res/values-es-rMX/strings.xml @@ -249,7 +249,7 @@ Desescojer como Dirección Principal Error en descifrar Nombre del dispositivo - Identificación del dispositivo + Identificación del dispositivo Clave del dispositivo Exportar claves de cifrado de extremo-a-extremo de salas Exportar claves de salas diff --git a/library/ui-strings/src/main/res/values-es/strings.xml b/library/ui-strings/src/main/res/values-es/strings.xml index 4eec90fbd6..bc4299c1bd 100644 --- a/library/ui-strings/src/main/res/values-es/strings.xml +++ b/library/ui-strings/src/main/res/values-es/strings.xml @@ -415,7 +415,7 @@ Dejar de Establecer como dirección principal Error de descifrado Nombre público - ID de sesión + ID de sesión Clave de sesión Exportar claves de salas con cifrado Extremo-a-Extremo Exportar claves de sala @@ -2518,4 +2518,136 @@ El destino se ha registrado de forma satisfactoria al servidor doméstico. Registración de punto final Siguiente + Pruébalo + Danos tu opinión + Acceder a espacios + Para simplificar ${app_name}, las pestañas son opcionales. Gestiónalas usando el menú en la esquina superior derecha. + ¡Bienvenido a una nueva interfaz! + Nada que reportar. + Bienvenido a ${app_name}, +\n%s. + %s +\nparece un poco vacío. + Sesiones inactivas + Verifica o cierra sesión de sesiones sin verificar. + Sesiones sin verificar + Mejora la seguridad de tu cuenta siguiendo estas recomendaciones. + Consejos de seguridad + + Inactiva por %1$d+ día (%2$s) + Inactiva por %1$d+ días (%2$s) + + Sin verificar · Última actividad %1$s + Verificada · Última actividad %1$s + Ver todos (%1$d) + Ver detalles + Verificar sesión + Sesión sin verificar + Sesión verificada + Tipo de dispositivo desconocido + Escritorio + Web + Móvil + Mostrar todas las sesiones (V2, WIP) + Auto aprovar widgets de Element Call y dar permisos de cámara y micrófono + + %d mensaje borrado + %d mensajes borrados + + Ubicación en tiempo real + Compartir ubicación + Debes tener el permiso correspondiente para compartir ubicaciones en esta sala. + No tienes permiso para compartir ubicaciones + No se pudo cargar el mapa +\nEste servidor doméstico puede que no esté configurado para mostrar mapas. + Los resultados podrán verse cuando la encuesta termine + MSC3061: Compartir claves de sala para mensajes anteriores + Abrir ajustes + Envía tu primer mensaje para invitar a %s + Los mensajes en esta sala están encriptados de extremo a extremo. + Este código QR parece incorrecto. Por favor, intente verificar con otro método. + No serás capaz de acceder al historial de mensajes encriptado. Restablece tu backup de mensajes seguro y las claves de verificación para empezar de cero. + No se ha podido verificar el dispositivo + Para más seguridad, verifica tus sesiones y cierra cualquiera que no reconozcas o hayas dejado de usar. + Otras sesiones + Sesiones + No se puede abrir este enlace: las comunidades han sido reemplazadas por espacios + Usuario / Email / Teléfono + ¿Eres una persona\? + Sigue las instrucciones enviadas a %s + Restablecer contraseña + Olvidé mi contraseña + Volver a enviar correo + ¿No recibiste ningún email\? + Sigue las instrucciones enviadas a %s + Verifica tu email + Volver a enviar código + Código enviado a %s + Confirma tu número de teléfono + Cerrar sesión en todos los dispositivos + Restablecer contraseña + Asegúrate de que tiene al menos 8 caracteres. + Elige una nueva contraseña + Nueva contraseña + Comprueba tu email. + %s te enviará un enlace de verificación + Código de confirmación + Número de teléfono + %s necesita verificar tu cuenta + Escribe tu número de teléfono + Email + %s necesita verificar tu cuenta + Introduce tu email + Por favor, lee las condiciones de uso de %s + Políticas del servidor + Ponte en contacto + ¿Deseas hospedar tu propio servidor\? + URL del servidor + ¿Cuál es la dirección de tu servidor\? + ¿Cuál es la dirección de tu servidor\? Será donde se guarden todos tus datos + Selecciona un servidor + ¡Hola de nuevo! + Editar + O + Dónde se guardarán tus conversaciones + Dónde se guardarán tus conversaciones + Debe tener al menos 8 caracteres + Otros pueden buscarte como %s + Crea tu cuenta + Abrir lista de espacios + Crear una nueva conversación o sala + Ir + Actualizando tus datos… + Personas + Favoritos + Sin leer + Todo + Lo sentimos, esta sala no se ha encontrado. +\nPor favor, inténtelo de nuevo.%s + Usar ajustes por defecto del sistema + Escoger manualmente + Tamaño automático de fuente + Escoger tamaño de la fuente + + %1$s y %2$d otro + %1$s y %2$d otros + + %1$s y %2$s + Email no verificado, comprueba tu bandeja de entrada + Aquí es donde tus nuevas solicitudes y invitaciones estarán. + Nada nuevo. + Invitaciones + Los espacios son una nueva forma de agrupar salas y personas. Crea un espacio para empezar. + No hay espacios aún. + A - Z + Actividad + Ordenar por + Mostrar recientes + Mostrar filtros + Ajustes de disposición + Explorar salas + Cambiar espacio + Crear sala + Iniciar conversación + Todas las conversaciones diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index a476ec4b3a..9bd1dd23b7 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -612,7 +612,7 @@ Need on alles katsejärgus olevad funktsionaalsused. Ole kasutamisel ettevaatlik. Dekrüptimise viga Avalik nimi - Sessiooni tunnus + Sessiooni tunnus Sessiooni võti Ekspordi jututubade läbiva krüptimise võtmed Ekspordi jututoa võtmed @@ -2592,8 +2592,8 @@ Ava seadistused Kõik vestlused Näita kõiki sessioone (V2, WIP) - Parima turvalisuse nimel verifitseeri kõik oma sessioonid ning logi välja neist, mida sa enam ei kasuta. - Muud sessioonid + Parima turvalisuse nimel verifitseeri kõik oma sessioonid ning logi välja neist, mida sa enam ei kasuta. + Muud sessioonid Sessionid Ava kogukondade loend Alusta uut vestlust või loo uus jututuba @@ -2610,4 +2610,53 @@ Tutvu jututubadega Loo jututuba Alusta vestlust + Verifitseerimata · Viimati kasutusel %1$s + Verifitseeritud · Viimati kasutusel %1$s + Näita kõiki (%1$d) + Vaata lisateavet + Verifitseeri sessioon + Verifitseerimata sessioon + Verifitseeritud sessioon + Tundmatu seadme tüüp + Töölauarakendus + Veebiliides + Mobiiltelefon + Vabandust, aga seda jututuba ei õnnestu leida. +\nPalun proovi hiljem uuesti.%s + Kutsed + Uut teavet ei leidu. + Kogukonnad on viis jututubade ja inimeste ühendamiseks. Alustamiseks võid luua uue kogukonna. + Siin veel pole kogukondi. + Vaheta kogukonda + Proovi nüüd + Tagasiside valikute nägemiseks klõpsi ülal paremal. + Jaga tagasisidet + Kogukonnad leiad alt paremalt kiiremini ja lihtsamini, kui varem. + Ligipääs kogukondadele + Et ${app_name}\'i kasutamine oleks lihtsam, siis kaardid on nüüd valikulised. Neid saad hallata ülal paremal avanevast menüüst. + Meie liidesel on nüüd uus vaade! + Kui sul on lugemata sõnumeid, siis nad on siit leitavad. + Hetkel siin polegi midagi põnevat. + Paljude võimalustega turvaline suhtlusrakendus sõprade, kogukondade ja tiimide jaoks. Alustamiseks loo mõni uus vestlus või liitu olemasoleva jututoaga. + %s, +\ntere tulemast ${app_name} kasutajaks. + Kogukonnad on võimalus jututubade ja inimeste ühendamiseks. Kasutades all paremal olevat nuppu lisa mõni olemasolev jututuba või loo uus. + %s +\ntundub olema tühjavõitu. + + Logi välja sellisest vanast sessioonist (vanem kui %1$d päev), mida sa enam ei kasuta. + Logi välja sellistest vanadest sessioonidest (vanemad kui %1$d päeva), mida sa enam ei kasuta. + + Mitteaktiivsed sessioonid + Logi verifitseerimata sessioonidest välja või verifitseeri nad. + Verifitseerimata sessioonid + Kui järgid neid soovitusi, siis sa parandad oma kasutajakonto turvalisust. + Turvalisusega seotud soovitused + + Pole olnud kasutusel %1$d+ päeva (%2$s) + Pole olnud kasutusel %1$d+ päeva (%2$s) + + Siin saavad olema sinu tulevased päringud ja kutsed. + Ahenda %s alamkogukonnad + Näita %s alamkogukondi diff --git a/library/ui-strings/src/main/res/values-eu/strings.xml b/library/ui-strings/src/main/res/values-eu/strings.xml index 7b27d1cc1d..f1f834ee04 100644 --- a/library/ui-strings/src/main/res/values-eu/strings.xml +++ b/library/ui-strings/src/main/res/values-eu/strings.xml @@ -406,7 +406,7 @@ Kontuan izan ekintza honek aplikazioa berrabiaraziko duela eta denbora bat behar Deszifratze errorea Izen publikoa - IDa + IDa Saioaren gakoa Esportatu E2E geletako gakoak diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index d1dbb57593..400a8121f9 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -678,7 +678,7 @@ این‌ها ویژگی‌های آزمایشی‌ای هستند که ممکن است به روش‌های نامنتظره‌ای حراب شوندا. با احتیاط استفاده کنید. تنظیم به عنوان نشانی اصلی نام عمومی - شناسهٔ نشست + شناسهٔ نشست کلید نشست برون‌ریزی کلید‌های اتاق‌های سرتاسری برون‌ریزی کلید‌های اتاق‌ها @@ -2601,8 +2601,8 @@ گشودن تنظیمات تمامی گپ‌ها نمایش تمامی نشست‌ها (ن۲، دح‌ت) - برای امنیت بیش‌تر، نشست‌هایتان را تأیید و از هر نشستی که تشخیصش نمی‌دهید یا دیگر استفاده نمی‌کنید خارج شوید. - دیگر نشست‌ها + برای امنیت بیش‌تر، نشست‌هایتان را تأیید و از هر نشستی که تشخیصش نمی‌دهید یا دیگر استفاده نمی‌کنید خارج شوید. + دیگر نشست‌ها نشست‌ها گشودن سیاههٔ فضاها ایجاد اتاق یا گفت‌وگویی جدید @@ -2619,4 +2619,85 @@ کاوش اتاق‌ها ایجاد اتاق آغاز گپ - + تأیید نشده · آخرین فعّالیت %1$s + تأیید شده · آخرین فعّالیت %1$s + دیدن همه (%1$d) + دیدن جزییات + تأیید نشست + نشست تأیید نشده + نشست تأیید شده + گونهٔ افزاره ناشناخته + میزکار + وب + تلفن همراه + متأسفانه این اتاق پیدا نشد. +\nلطفاً بعداً دوباره تلاش کنید.%s + دعوت‌ها + زدن بالا سمت چپ برای دیدن گزینهٔ بازخورد. + دسترسی به فضاهایتان (پایین سمت چپ) سریع‌تر و ساده‌تر از همیشه. + برای ساده‌سازی ${app_name} زبانه‌ها اختیاری شده‌اند. مدیریت با استفاده از فهرست بالا سمت چپ. + این جایی است که پیام‌های ناخوانده‌تان در صورت وجود ظاهر خواهند شد. + کارهٔ گپ امن یکپارچه برای گروه‌ها، دوستان و سازمان‌ها. برای آغاز، گپی ساخته یا به اتاقی بپیوندید. + فضاها راهی جدید برای گروه‌بندی اتاق‌ها و افراد است. با استفاده از دکمهٔ پایین سمت چپ فضایی ساخته یا اتاقی را بیفزایید. + %s +\nکمی خالی به نظر می‌رسد. + + در نظر گرفتن خروج از نشست‌های قدیمی (۱ روز یا بیش‌تر) که دیگر استفاده نمی‌کنید. + در نظر گرفتن خروج از نشست‌های قدیمی (%1$d روز یا بیش‌تر) که دیگر استفاده نمی‌کنید. + + تأیید یا خروج از نشست‌های تأییدنشده. + بهبود امنیت حسابتان با پیروی از این توصیه‌ها. + + غیرفعّال برای بیش از %1$d روز (%2$s) + غیرفعّال برای بیش از %1$d روز (%2$s) + + این جایی است که درخواست‌ها و دعوت‌های جدیدتان خواهند بود. + فضاها راهی جدید برای گروه‌بندی اتاق‌ها و افراد است. برای آغاز، فضایی بسازید. + بیازماییدش + دادن بازخورد + دسترسی به فضاها + به نمایی جدید خوش آمدید! + چیزی برای گزارش نیست. + %s +\nبه ${app_name} خوش آمدی. + نشست‌های غیرفعّال + نشست‌های تأیید نشده + توصیه‌های امنیتی + چیز جدیدی نیست. + هنوز فضایی وجود ندارد. + جمع کردن فرزندان %s + گسترش فرزندان %s + تغییر فضا + نشانی آی‌پی + واپسین فعّالیت + نام نشست + اطّلاعات برنامه، افزاره و فعّالیت. + جزییات نشست + پاک‌سازی پالایه + هیچ نشست غیرفعّالی پیدا نشد. + هیچ نشست تأیید نشده‌ای پیدا نشد. + هیچ نشست تأیید نشده‌ای پیدا نشد. + غیرفعّال + تأیید نشده + برای بهترین امنیت، از هرنشستی که تشخیصش نمی‌دهید یا دیگر استفاده نمی‌کنید، خارج شوید. + تأیید شده + پالایه + غیرفعّال + نا آماده برای پیام‌رسانی امن + تأیید نشده + آمادهٔ پیام‌رسانی امن + تأیید شده + تمامی نشست‌ها + پالایه + آخرین فعّالیت %1$s + افزاره + نشست + نشست کنونی + برای بهترین امنیت و اطمینان این نشست را تأیید کرده یا خارج شوید. + تأیید نشست کنونیتان برای پیام‌رسانی امن. + این نشست برای پیام‌رسانی امن آماده است. + نشست کنونیتان برای پیام‌رسانی امن آماده است. + ایجاد پیام خصوصی فقط در نخستین پیام + المنتی ساده شده با زبانه‌های انتخابی + به کار انداختن چینش جدید + \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-fi/strings.xml b/library/ui-strings/src/main/res/values-fi/strings.xml index fde2502ae0..a576e7f0dc 100644 --- a/library/ui-strings/src/main/res/values-fi/strings.xml +++ b/library/ui-strings/src/main/res/values-fi/strings.xml @@ -366,7 +366,7 @@ Kumoa pääosoitteeksi asettaminen Salauksenpurkuvirhe Julkinen nimi - Istunnon tunnus + Istunnon tunnus Istunnon avain Vie salatun huoneen avaimet Vie huoneen avaimet diff --git a/library/ui-strings/src/main/res/values-fr-rCA/strings.xml b/library/ui-strings/src/main/res/values-fr-rCA/strings.xml index 29a618f415..94db2935a7 100644 --- a/library/ui-strings/src/main/res/values-fr-rCA/strings.xml +++ b/library/ui-strings/src/main/res/values-fr-rCA/strings.xml @@ -778,7 +778,7 @@ Exporter les clés des salons Exporter les clés E2E des salons Clé de la session - Identifiant de session + Identifiant de session Nom public Erreur de déchiffrement Thème diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index 0bc033c93a..5a19ccf2da 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -346,7 +346,7 @@ Désactiver comme adresse principale Erreur de déchiffrement Nom public - Identifiant de session + Identifiant de session Clé de la session Exporter les clés E2E des salons Exporter les clés des salons @@ -2601,8 +2601,8 @@ Ouvrir les paramètres Toutes les conversations Afficher toutes les sessions (V2, en cours) - Pour une meilleure sécurité, vérifiez vos sessions et déconnectez toutes les sessions que vous ne connaissez pas ou que vous n’utilisez plus. - Autres sessions + Pour une meilleure sécurité, vérifiez vos sessions et déconnectez toutes les sessions que vous ne connaissez pas ou que vous n’utilisez plus. + Autres sessions Sessions Ouvrir la liste des espaces Créer une nouvelle conversation ou salon @@ -2619,4 +2619,53 @@ Parcourir les salons Créer un salon Commencer une discussion + Non vérifiée · Dernière activité %1$s + Vérifié · Dernière activité %1$s + Tout voir (%1$d) + Voir les détails + Vérifier la session + Session non vérifiée + Session vérifiée + Type de périphérique inconnu + Ordinateur + Web + Portable + Désolé, impossible de trouver ce salon. +\nVeuillez réessayer plus tard.%s + Invitations + Essayez + Appuyez en haut à droite pour les options des avis. + Donner mon avis + Accédez à vos espaces (en bas à droite) plus rapidement et facilement qu’avant. + Accéder aux espaces + Pour simplifier Element, les onglets sont désormais facultatifs. Gérez les depuis le menu en haut à droite. + Bienvenu dans une nouvelle vue ! + C\'est ici que vos messages non-lus s’afficheront lorsque vous en aurez. + Rien à signaler. + La messagerie sécurisée tout-en-un pour les équipes, les amis, et les organisations. Créez une discussion ou rejoignez un salon pour démarrer. + Bienvenue dans ${app_name}, +\n%s. + Les espaces sont un nouveau moyen de grouper les salons et les gens. Ajoutez un salon, ou créez en un nouveau à l’aide du bouton en bas à droite. + %s +\na l’air un peu vide. + + Pensez à vous déconnecter des anciennes sessions (%1$d jour ou plus) que vous n’utilisez plus. + Pensez à vous déconnecter des anciennes sessions (%1$d jours ou plus) que vous n’utilisez plus. + + Sessions inactives + Vérifier ou déconnecter les sessions non vérifiées. + Sessions non vérifiées + Améliorez la sécurité de votre compte à l’aide de ces recommandations. + Recommandations de sécurité + + Inactif depuis %1$d+ jour (%2$s) + Inactif depuis %1$d+ jours (%2$s) + + C’est l’endroit où se trouveront vos nouvelles requêtes et invitations. + Rien de neuf. + Les espaces sont un nouveau moyen de regrouper les salons et les gens. Créez un espace pour commencer. + Pas d’espace pour l’instant. + Réduire %s enfants + Développer %s enfants + Changer d’espace diff --git a/library/ui-strings/src/main/res/values-gl/strings.xml b/library/ui-strings/src/main/res/values-gl/strings.xml index e6d26a63e5..c1e4e40a81 100644 --- a/library/ui-strings/src/main/res/values-gl/strings.xml +++ b/library/ui-strings/src/main/res/values-gl/strings.xml @@ -380,7 +380,7 @@ Tema Fallo ao descifrar Nome do dispositivo - ID de sesión + ID de sesión Chave do dispositivo Exportar chaves E2E da sala Exportar chaves da sala diff --git a/library/ui-strings/src/main/res/values-hr/strings.xml b/library/ui-strings/src/main/res/values-hr/strings.xml index dc5930b933..6d52e5cd96 100644 --- a/library/ui-strings/src/main/res/values-hr/strings.xml +++ b/library/ui-strings/src/main/res/values-hr/strings.xml @@ -572,7 +572,7 @@ Tema Greška u dešifriranju Javni naziv - Identitet + Identitet Ključ sesije Izvezi sobne ključeve za E2E Izvezi sobne ključeve diff --git a/library/ui-strings/src/main/res/values-hu/strings.xml b/library/ui-strings/src/main/res/values-hu/strings.xml index a35595fb36..3068556fe4 100644 --- a/library/ui-strings/src/main/res/values-hu/strings.xml +++ b/library/ui-strings/src/main/res/values-hu/strings.xml @@ -157,7 +157,7 @@ %s megváltoztatta a szerver ACL-eket ehhez a szobához. • IP címet hosztnévként használó szerverek tiltva vannak. • IP címet hosztnévként használó szerverek engedélyezve vannak. - • Engedélyezve vannak azok a szerverek, amik illeszkednek erre: %s + • Engedélyezve vannak azok a szerverek, amik illeszkednek erre: %s. • Tiltva vannak azok a szerverek, amik illeszkednek erre: %s Beállítottad a szerver ACL-eket ehhez a szobához. %s beállította a szerver ACL-eket ehhez a szobához. @@ -351,7 +351,7 @@ Kiszedés fő címek közül Visszafejtés hiba Nyilvános név - Munkamenet-azonosító + Munkamenet-azonosító Munkamenet kulcs E2E szoba kulcsok exportálása Szoba kulcsok exportálása @@ -2600,4 +2600,72 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze %1$s és %2$s Minden beszélgetés + Nem ellenőrzött - Utolsó aktivitás %1$s + Ellenőrzött - Utolsó tevékenység %1$s + Összes megtekintése (%1$d) + Részletek megtekintése + Munkamenet hitelesítése + Ellenőrizetlen munkamenet + Ellenőrzött munkamenet + Ismeretlen eszköztípus + Asztali + Web + Mobil + Minden munkamenet megjelenítése (V2, WIP) + A legjobb biztonság érdekében ellenőrizd a munkameneteket, és jelentkezz ki minden olyan munkamenetből, melyet már nem ismersz fel vagy nem használsz. + Más munkamenetek + Munkamenetek + Nyitott területek listája + Új beszélgetés vagy szoba létrehozása + Emberek + Kedvencek + Olvasatlan + Mind + Sajnáljuk, ez a szoba nem található. +\nKérjük, próbáld meg később újra.%s + Meghívók + A - Z + Aktivitás + Rendezés + Legfrissebbek megjelenítése + Szűrők megjelenítése + Elrendezési beállítások + Szobák felfedezése + Szoba létrehozása + Chat indítása + Próbáld ki + Visszajelzés adása + A terekhez való hozzáférés (jobbra lent) gyorsabb és egyszerűbb mint valaha. + Hozzáférés a terekhez + ${app_name} egyszerűsítéséhez a lapok mostantól választhatók. Beállítani a jobb felső menüből lehet. + Üdv az új kinézetben! + Ez az a hely ahol az olvasatlan üzeneteid megjelennek, ha lesznek. + Nincs semmi említésre méltó. + A minden-egyben biztonságos csevegő alkalmazás csapatoknak, barátoknak és szervezeteknek. Kezd egy csevegést vagy lépj be egy meglévő szobába kezdésnek. + Üdv itt: ${app_name}! +\n%s. + Szobák és emberek csoportokba rendezésének új mondja a terek használata. Létező szoba hozzáadása vagy új készítése a jobb alsó gombbal. + %s +\nkicsit üresnek tűnik. + Nem aktív munkamenetek + Ellenőrizd vagy jelentkezz ki az ellenőrizetlen munkamenetekből. + Meg nem erősített munkamenetek + Javítsa a fiókja biztonságát azzal, hogy követi a következő javaslatokat. + Biztonsági javaslatok + Semmi új. + Terekkel lehet szobákat és személyeket csoportokba rendezni. Készíts egyet indulásnak. + Nincsenek terek egyelőre. + %s összezárása + %s kinyitása + Tér cseréje + A visszajelzési lehetőségekhez koppint jobb felső sarokba. + + Fontold meg, hogy a régi már nem használt (%1$d napja vagy régebben) munkamenetből kijelentkezel. + Fontold meg, hogy a régi már nem használt (%1$d napja vagy régebben) munkamenetből kijelentkezel. + + + %1$d+ napja inaktív (%2$s) + %1$d+ napja inaktív (%2$s) + + Itt láthatók a meghívók és elvégzendő műveletek. diff --git a/library/ui-strings/src/main/res/values-in/strings.xml b/library/ui-strings/src/main/res/values-in/strings.xml index 031e13ed63..3b30950bd1 100644 --- a/library/ui-strings/src/main/res/values-in/strings.xml +++ b/library/ui-strings/src/main/res/values-in/strings.xml @@ -47,8 +47,8 @@ Hanya kontak Matrix Ruangan Laporan kutu - Aplikasi gagal saat terakhir digunakan. Apakah Anda ingin membuka halaman laporan kegagalan\? - Gabung di Ruangan + Aplikasi mogok saat terakhir digunakan. Apakah Anda ingin membuka halaman laporan kemogokan\? + Bergabung ke Ruangan Mulai Panggilan Suara Masuk Mulai Panggilan Video @@ -69,7 +69,7 @@ TIDAK Lanjut Hapus - Gabung + Bergabung Tolak Nanti Kirim catatan gangguan @@ -88,7 +88,7 @@ Kirim tampilan layar Mohon uraikan kutu tersebut. Apa yang Anda lakukan\? Apa yang Anda harapkan terjadi\? Apa yang sebenarnya terjadi\? Catatan dari klien akan dikirim bersama laporan gangguan ini untuk mendalami kendala yang Anda temukan. Laporan gangguan ini, termasuk catatan dan tangkapan layar, tidak akan terlihat secara umum. Jika Anda hanya ingin mengirimkan tulisan di atas, silakan hapus centang: - Sepertinya Anda mengguncang ponsel akibat frustrasi. Apakah Anda ingin membuka halaman laporan kutu\? + Sepertinya Anda mengguncang ponsel akibat emosi. Apakah Anda ingin membuka halaman laporan kutu\? Pengiriman laporan kutu gagal (%s) Kemajuan (%s%%) Nama Pengguna @@ -122,9 +122,9 @@ Kirim Sticker Ambil foto Ambil video - Saat ini Anda belum memiliki pak stiker. + Saat ini Anda belum memiliki paket stiker apa pun. \n -\nMau tambah sekarang\? +\nIngin tambah sekarang\? Maaf, tidak ada aplikasi eksternal yang mendukung apa yang ingin dilakukan. Meminta ulang kunci enkripsi dari perangkat Anda yang lain. Jalankan ${app_name} di perangkat yang dapat mendekripsi pesan tersebut agar kunci dapat dikirim ke perangkat ini. @@ -146,8 +146,8 @@ Sembunyikan semua pesan dari pengguna ini Tunjukkan semua pesan dari pengguna ini Sebut - Anda tidak akan dapat mengembalikan perubahan ini setelah Anda mengangkat pengguna ini agar memiliki kuasa yang setara dengan Anda. -\nApakah anda yakin untuk melanjutkan\? + Anda tidak akan dapat mengembalikan perubahan ini setelah Anda mengangkat pengguna ini agar memiliki daya yang setara dengan Anda. +\nApakah Anda yakin untuk melanjutkan\? Melakukan pencekalan pengguna akan mengeluarkannya dari ruangan ini dan mencegahnya untuk kembali masuk. Gagal terjawab oleh pihak lain. %s sedang mengetik… @@ -210,7 +210,7 @@ Tidak dapat membuat widget. Gagal mengirim permohonan. Tingkat energi harus bilangan positif. - Anda tidak tergabung dengan ruangan ini. + Anda tidak di ruangan ini. Anda tidak memiliki permisi untuk melakukan itu di ruangan ini. Tidak ada room_id dalam permohonan. Tidak ada user_id dalam permohonan. @@ -228,7 +228,7 @@ Menghapus cekalan pengguna dengan id berikut Tentukan tingkat kuasa seorang pengguna Undang pengguna dengan id berikut bergabung ke ruangan ini - Gabung ke ruangan dengan alamat berikut + Bergabung ke ruangan dengan alamat berikut Tinggalkan ruang Tentukan topik ruang Keluarkan pengguna dengan id berikut @@ -251,10 +251,10 @@ Nonaktifkan Akun Ini akan mengakibatkan akun Anda tidak dapat digunakan secara permanen. Anda tidak akan dapat masuk dan orang lain tidak dapat mendaftar ulang dengan ID pengguna yang sama. Ini akan mengakibatkan akun Anda keluar dari semua ruangan tempat Anda berpartisipasi serta menghapus semua detail akun dari server identitas Anda. Tindakan ini tidak dapat diubah. \n -\nMenonaktifkan akun Anda tidak membuat kami melupakan pesan-pesan yang Anda kirim secara default. Jika Anda ingin kami melupakan pesan-pesan Anda, mohon centang kotak berikut. +\nMenonaktifkan akun Anda tidak membuat kami melupakan pesan-pesan yang Anda kirim secara bawaan. Jika Anda ingin kami melupakan pesan-pesan Anda, mohon centang kotak berikut. \n \nKeterbacaan pesan di Matrix serupa dengan email. Dengan kami melupakan pesan-pesan Anda berarti pesan-pesan yang Anda kirim tidak akan dibagikan kepada pengguna baru ataupun yang belum terdaftar, tetapi pengguna yang terdaftar yang mempunyai mengakses pesan-pesan tersebut masih dapat mengakses salinan mereka. - Mohon lupakan semua pesan yang telah saya kirim ketika akun saya dideaktivasi (Peringatan: ini akan mengakibatkan pengguna di masa depan melihat percakapan yang tidak lengkap) + Mohon lupakan semua pesan yang telah saya kirim ketika akun saya dinonaktifkan (Peringatan: ini akan mengakibatkan pengguna di masa depan melihat percakapan yang tidak lengkap) Nonaktifkan Akun Mohon masukkan kata sandi Anda. Ruangan ini telah berubah dan tidak lagi aktif. @@ -276,7 +276,7 @@ Jangan kirim pesan terenkripsi ke perangkat yang tidak terverifikasi dari perangkat ini. TIDAK terverifikasi Verifikasi - Untuk memastikan perangkat dapat dipercaya, mohon kontak pengguna dengan medium lain (misalnya tatap muka atau panggilan telepon) dan tanya apakah kunci yang mereka lihat di Pengaturan Pengguna untuk perangkat ini cocok dengan kunci berikut: + Konfirmasi dengan membandingkan berikut ini dengan Pengaturan Pengguna di sesi Anda yang lain: Apabila cocok, tekan tombol verifikasi berikut. Apabila tidak, seseorang sedang menyadap perangkat ini dan mungkin perlu diblokir. Di masa mendatang proses verifikasi ini akan dimutakhirkan. @@ -290,7 +290,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Siapa pun Hanya anggota (dimulai sejak opsi ini dipilih) Hanya anggota (dimulai sejak mereka diundang) - Hanya anggota (dimulai sejak mereka bergabung) + Hanya anggota (sejak mereka bergabung) Pengguna yang dicekal Lanjutan ID internal ruangan ini @@ -301,7 +301,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Tema Kesalahan dekripsi Nama perangkat - ID Sesi + ID Sesi Kunci perangkat Ekspor kunci ruangan terenkripsi Ekspor ruangan kunci @@ -378,11 +378,11 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Keluarkan Periksa Keadaan Pemberitahuan Hasil diagnosa pemeriksaan keadaan - Lansungkan Ujicoba + Jalankan Pengujian Berlangsung… (%1$d of %2$d) Diagnosa dasar berlangsung lancar. Apabila Anda masih belum dapat menerima pemberitahuan, mohon kirim laporan kutu untuk kami selidiki. - Satu atau beberapa ujicoba gagal, coba sugesti yang kami tawarkan. - Satu atau beberapa ujicoba gagal, mohon kirim laporan kutu untuk kami selidiki. + Satu atau beberapa ujian gagal, coba saran yang kami tawarkan. + Satu atau beberapa ujian gagal, mohon kirim laporan kutu untuk kami selidiki. Pengaturan Sistem. Pemberitahuan diperbolehkan dalam pengaturan sistem. Notifikasi dinonaktifkan dalam pengaturan sistem. @@ -400,7 +400,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Perbolehkan Pemeriksaan Layanan Google Play APK Layanan Google Play ditemukan dan telah diperbaharui. - ${app_name} menggunakan Layanan Google Play untuk mendorong pesan tapi tampaknya tidak diatur sebagaimana harusnya. + ${app_name} menggunakan Layanan Google Play untuk mendorong pesan tapi tampaknya tidak diatur sebagaimana harusnya: \n%1$s Perbaiki Layanan Google Play Token Firebase @@ -417,7 +417,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Layanan tidak akan mulai ketika perangkat dinyalakan kembali, Anda tidak akan menerima pemberitahuan hingga Anda membuka ${app_name}. Perbolehkan memulai ketika perangkat dinyalakan Periksa halangan di balik layar - Larangan background dinonaktifkan untuk ${app_name}. Percobaan ini sebaiknya dijalankan menggunakan jaringan mobile data (bukan WIFI). + Larangan latar belakang dinonaktifkan untuk ${app_name}. Percobaan ini sebaiknya dijalankan menggunakan jaringan data ponsel (bukan WiFi). \n%1$s Larangan background dinonaktifkan untuk ${app_name}. \nAktivitas yang dilakukan aplikasi ini akan terhalang ketika beroperasi di balik layar, dan ini dapat mempengaruhi pemunculan notifikasi. @@ -446,7 +446,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. [%1$s] \nError ini di luar kendali ${app_name} dan menurut Google, error ini muncul ketika terlalu banyak aplikasi terdaftar dengan FCM pada perangkat tersebut. Error ini tidak seharusnya mempengaruhi pengguna biasa. [%1$s] -\nError ini di luar kendali ${app_name}, dan dapat muncul karena berbagai alasan. Coba lagi nanti, atau Anda juga dapat memeriksa apabila penggunaan jaringan data Layanan Google Play tidak terhalang oleh sistem, atau waktu pada perangkat sudah benar, atau ini dapat terjadi pada ROM tidak resmi. +\nKesalahan ini di luar kendali ${app_name}, dan dapat muncul karena berbagai alasan. Coba lagi nanti, atau Anda juga dapat memeriksa apabila penggunaan jaringan data Layanan Google Play tidak terhalang oleh sistem, atau waktu pada perangkat sudah benar, atau ini dapat terjadi pada ROM tidak resmi. [%1$s] \nError ini di luar kendali ${app_name}. Tidak terdapat akun Google pada perangkat. Mohon buka pengelola akun dan tambahkan akun Google. Tambah Akun @@ -493,7 +493,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. %s melakukan panggilan suara. Anda melakukan panggilan video. %s melakukan panggilan video. - Anda mengubah nama kamar menjadi: %1$s + Anda mengubah nama ruangan menjadi: %1$s %1$s mengubah nama ruangan menjadi: %2$s Anda mengubah avatar ruangan ini %1$s mengubah avatar ruangan ini @@ -546,7 +546,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Aplikasi ini sedang menunggu push Aplikasi ini menerima push Gagal menerima push. Solusinya adalah untuk menginstal ulang aplikasi. - Percobaan Push + Percobaan Dorongan Pastikan Anda mengeklik tautan di email yang telah kami kirimkan kepada Anda. Hapus %s\? Tidak ada nomor telepon yang ditambahkan ke akun Anda @@ -578,7 +578,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Batalkan pencekalan pengguna Alasan untuk mencekal Cekal pengguna - Pengguna yang dikeluarkan akan menghilangkannya dari ruangan ini. + Pengguna akan dikeluarkan dari ruangan ini. \n \nUntuk mencegah mereka bergabung lagi, Anda seharusnya mencekalnya. Alasan untuk mengeluarkan @@ -593,7 +593,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Abaikan pengguna Turunkan Anda tidak akan dapat membatalkan perubahan ini karena Anda menurunkan diri sendiri, jika Anda adalah pengguna istimewa terakhir di ruangan itu akan tidak mungkin untuk mendapatkan kembali hak istimewa. - Turunkan dirimu\? + Turunkan diri Anda\? Batalkan undangan Ruangan ini tidak umum. Anda tidak akan dapat bergabung kembali tanpa undangan. Izinkan untuk mengakses kontak. @@ -657,7 +657,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Gagal menambahkan widget Anda tidak dapat melakukan panggilan dengan diri sendiri, tunggu untuk peserta untuk menerima undangan Anda tidak dapat melakukan panggilan dengan diri sendiri - Pertemuan menggunakan kebijakan keamanan dan izin Jitsi. Semua orang saat ini berada di ruangan akan melihat undangan untuk bergabung saat pertemuan Anda sedang berlangsung. + Pertemuan menggunakan kebijakan keamanan dan perizinan Jitsi. Semua orang saat ini berada di ruangan akan melihat undangan untuk bergabung saat pertemuan Anda sedang berlangsung. Mulai rapat video Mulai rapat audio Anda tidak memiliki izin untuk memulai panggilan @@ -675,19 +675,19 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Putuskan Batalkan Tidak Ada - Standar Sistem + Bawaan Sistem Anda mengaktifkan enkripsi ujung-ke-ujung. (algoritma tidak dikenali %1$s). %1$s mengaktifkan enkripsi ujung-ke-ujung. (algoritma tidak dikenali %2$s). Anda mengaktifkan enkripsi ujung-ke-ujung. %1$s mengaktifkan enkripsi ujung-ke-ujung. - Anda telah mencegah para tamu untuk bergabung ruangan. - %1$s telah mencegah para tamu untuk bergabung ruangan. - Anda telah mencegah para tamu untuk bergabung ruangan. - %1$s telah mencegah para tamu untuk bergabung ruangan. - %1$s telah mengizinkan para tamu untuk bergabung ruangan. - Anda telah mengizinkan para tamu untuk bergabung ruangan. - Anda telah mengizinkan para tamu untuk bergabung disini. - %1$s telah mengizinkan para tamu untuk bergabung disini. + Anda telah mencegah para tamu untuk bergabung ke ruangan. + %1$s telah mencegah para tamu untuk bergabung ke ruangan. + Anda telah mencegah para tamu untuk bergabung ke ruangan. + %1$s telah mencegah para tamu untuk bergabung ke ruangan. + %1$s telah mengizinkan para tamu untuk bergabung ke ruangan. + Anda telah mengizinkan para tamu untuk bergabung ke ruangan. + Anda telah mengizinkan para tamu untuk bergabung di sini. + %1$s telah mengizinkan para tamu untuk bergabung di sini. Anda mengubah alamat untuk ruangan ini. %1$s mengubah alamat untuk ruangan ini. Anda mengubah alamat utama dan alamat alternatif untuk ruangan ini. @@ -740,12 +740,12 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. %1$s meninggalkan ruangan. Alasan: %2$s Anda meninggalkan ruangan. Alasan: %1$s %1$s meninggalkan ruangan. Alasan: %2$s - Anda bergabung. Alasan %1$s - %1$s bergabung. Alasan %2$s - %1$s bergabung ruangan. Alasan: %2$s + Anda bergabung. Alasan: %1$s + %1$s bergabung. Alasan: %2$s + %1$s bergabung ke ruangan. Alasan: %2$s %1$s mengundang Anda. Alasan: %2$s Anda mengundang %1$s. Alasan: %2$s - Anda bergabung ruangan. Alasan %1$s + Anda bergabung ke ruangan. Alasan: %1$s %1$s mengundang %2$s. Alasan: %3$s Undangan Anda. Alasan: %1$s Undangan %1$s. Alasan: %2$s @@ -800,12 +800,12 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. %1$s menerima undangan untuk %2$s Anda membatalkan undangan untuk %1$s %1$s membatalkan undangan untuk %2$s - Anda membatalkan undangan untuk %1$s untuk bergabung ruangan - %1$s membatalkan undangan untuk %2$s untuk bergabung ruangan + Anda membatalkan undangan untuk %1$s untuk bergabung ke ruangan + %1$s membatalkan undangan untuk %2$s untuk bergabung ke ruangan Anda mengundang %1$s %1$s mengundang %2$s - Anda mengirimkan undangan ke %1$s untuk bergabung ruangan - %1$s mengirimkan undangan ke %2$s untuk bergabung ruangan + Anda mengirimkan undangan ke %1$s untuk bergabung ke ruangan + %1$s mengirimkan undangan ke %2$s untuk bergabung ke ruangan Anda menghapus avatar ruangan %1$s menghapus avatar ruangan Anda menghapus topik ruangan @@ -833,8 +833,8 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Maaf, terjadi kesalahan Mohon masukkan nama pengguna. Diam - Penurunan harga telah dinonaktifkan. - Penurunan harga telah diaktifkan. + Markdown telah dinonaktifkan. + Markdown telah diaktifkan. Perintah \"%s\" membutuhkan parameter tambahan, atau beberapa parameter salah. Abaikan Permintaan Pembagian Kunci @@ -965,9 +965,9 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Beritahu saya untuk Putar suara rana Pilih - Sumber media default + Sumber media bawaan Pilih - Kompresi default + Kompresi bawaan Media Kelola email dan nomor telepon yang ditautkan ke akun Matrix Anda Email dan nomor telepon @@ -992,7 +992,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Gunakan perintah /confetti atau kirim pesan yang berisi ❄️ atau 🎉 Tampilkan efek chat Gunakan pengelola integrasi untuk mengelola bot, jembatan, widget, dan paket stiker. -\nPengelola integrasi menerima data konfigurasi, dan dapat memodifikasi widget, mengirim undangan ruang, dan mengatur tingkat daya dengan sepengetahuan Anda. +\nPengelola integrasi menerima data konfigurasi, dan dapat memodifikasi widget, mengirim undangan ruang, dan mengatur tingkat daya dengan pengetahuan Anda. Integrasi %d detik @@ -1047,11 +1047,11 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Email ini tidak terkait dengan akun apa pun. Aplikasi tidak dapat membuat akun di homeserver ini. \n -\nApakah Anda ingin mendaftar menggunakan client web\? +\nApakah Anda ingin mendaftar menggunakan klien web\? Maaf, server ini tidak menerima akun baru. Aplikasi tidak dapat masuk ke homeserver ini. Homeserver mendukung jenis masuk berikut: %1$s. \n -\nApakah Anda ingin masuk menggunakan client web\? +\nApakah Anda ingin masuk menggunakan klien web\? Ada kesalahan terjadi saat memuat halaman: %1$s (%2$d) Masukkan alamat server yang ingin Anda gunakan Masukkan alamat Modular Element atau Server yang ingin Anda gunakan @@ -1076,7 +1076,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Lainnya Pelajari lebih lanjut Hosting premium untuk organisasi - Bergabunglah dengan jutaan orang secara gratis di server publik terbesar + Bergabung dengan jutaan orang secara gratis di server publik terbesar Sama seperti email, akun memiliki satu tempat, tetapi Anda dapat berkomunikasi dengan siapa saja Pilih server Mulai @@ -1374,7 +1374,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. BUAT Pesan Langsung Ruangan - Ruangan ini tidak dapat ditampilkan. Apakah Anda masih mau bergabung\? + Ruangan ini tidak dapat ditampilkan. Apakah Anda masih ingin bergabung\? Ruangan ini tidak dapat di akses di waktu ini. \nCoba lagi nanti, atau tanya admin ruangan untuk memeriksa jika Anda punya akses. Ruangan ini tidak dapat di tampilkan @@ -1424,7 +1424,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Tidak ada informasi cryptographic unstable stable - Versi Default + Versi Bawaan Versi Ruangan 👓 Batas tidak diketahui. Homeserver Anda menerima lampiran (file, media, dsb.) dengan ukuran hingga %s. @@ -1435,7 +1435,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Kelola Sesi Tampilkan Semua Sesi Sesi Aktif - Admin server Anda telah menonaktifkan enkripsi ujung-ke-ujung secara default di kamar pribadi & pesan langsung. + Admin server Anda telah menonaktifkan enkripsi ujung-ke-ujung secara bawaan di ruangan & Pesan Langsung privat. Tanda Tangan Silang dinonaktifkan Tanda Tangan Silang diaktifkan. \nKunci dipercaya. @@ -1710,7 +1710,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Tambahkan ruangan dan space yang sudah ada Anda adalah admin satu-satunya di space ini. Meninggalkannya berarti siapa saja tidak akan mempunyai kontrol atas space-nya. Anda tidak akan dapat bergabung lagi kecuali jika Anda diundang lagi. - Anda orang satu-satunya di sini. Jika Anda tinggalkan, siapa saja tidak dapat bergabung di masa depan, termasuk Anda. + Anda adalah orang satu-satunya di sini. Jika Anda tinggalkan, siapa saja tidak dapat bergabung di masa depan, termasuk Anda. Apakah Anda yakin untuk meninggalkan %s\? Tinggalkan Tambahkan ruangan @@ -2015,7 +2015,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Gagal mengimpor kunci Menunggu untuk %s… Hampir selesai! Menunggu untuk konfirmasi… - Hampir selesai! Apakah perangkat yang lain menunjukkan centang yang sama\? + Hampir selesai! Apakah perangkat yang lain menunjukkan sebuah centang\? "Topik: " Tambahkan topik %s untuk memberi tahu orang-orang tentang ruangan ini. @@ -2043,7 +2043,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Mengsinkronisasikan Kunci Penandatanganan Diri Mengsinkronisasikan Kunci Pengguna Mengsinkronisasikan Kunci Utama - Mendefinisikan Kunci SSSS default + Mendefinisikan Kunci SSSS bawaan Membuat kunci aman dari frasa sandi Mempublikasikan kunci identitas yang telah dibuat Selesai @@ -2071,7 +2071,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Jika Anda batalkan, Anda tidak dapat membaca pesan terenkripsi di perangkat ini dan pengguna lain tidak akan mempercayainya Akun Anda mungkin dikompromikan Ini bukan saya - Login baru. Apakah itu Anda\? + Pemasukan baru. Apakah itu Anda\? Segarkan Akses riwayat pesan terenkripsi Ekspor Audit @@ -2091,13 +2091,13 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Kirim gambar dengan ukuran asli - Apakah Anda mau mengirim lampiran ini ke %1$s\? + Apakah Anda ingin mengirim lampiran ini ke %1$s\? Hapus… Tidak dapat menemukan rahasia di penyimpanan Jika Anda tidak dapat mengakses sesi yang sudah ada Peringatan tingkat kepercayaan Level kepercayaan peringatan - Level kepercayaan default + Level kepercayaan bawaan Dipilih Video mempunyai draf yang belum dikirim @@ -2109,7 +2109,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Buka widget Tangkap layar Gagal mengotentikasi - ${app_name} meminta Anda untuk memasukkan kredential untuk melakukan aksi ini. + ${app_name} meminta Anda untuk memasukkan kredensial untuk melakukan tindakan ini. Otentikasi Ulang Dibutuhkan Geser untuk mengakhirkan panggilan Orang tak dikenal @@ -2155,7 +2155,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Koneksi ke server telah hilang Tidak Ya - Hampir selesai! Apakah %s menampilkan centang yang sama\? + Hampir selesai! Apakah %s menampilkan sebuah centang\? Kode QR Atur Ulang Kunci Memulai Tanda Tangan Silang @@ -2186,9 +2186,9 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Izin space Menghapus cekalan akan mengizinkan pengguna untuk bergabung ke space lagi. Mencekal pengguna akan mengeluarkan pengguna dari space ini dan mencegah pengguna untuk bergabung lagi. - mengeluarkan pengguna akan mengeluarkannya dari space ini. + Pengguna akan dikeluarkan dari space ini. \n -\nUntuk mencegah pengguna untuk bergabung lagi, Anda seharusnya cekal pengguna itu saja. +\nUntuk mencegah mereka untuk bergabung lagi, Anda seharusnya mencekalnya. Berhenti Merekam Menambahkan ( ͡° ͜ʖ ͡°) ke pesan teks biasa Tidak ada kebijakan yang disediakan oleh server identitasnya @@ -2553,8 +2553,8 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Email belum diverifikasi, periksa kotak masuk Anda Semua Obrolan Tampilkan Semua Sesi (V2, Dalam Pengembangan) - Untuk keamanan terbaik, verifikasi sesi Anda dan keluarkan sesi apa pun yang Anda tidak kenal atau Anda tidak gunakan lagi. - Sesi lainnya + Untuk keamanan terbaik, verifikasi sesi Anda dan keluarkan sesi apa pun yang Anda tidak kenal atau Anda tidak gunakan lagi. + Sesi lainnya Sesi Buka daftar space Buat percakapan atau ruangan baru @@ -2571,4 +2571,51 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Jelajahi Ruangan Buat Ruangan Mulai Obrolan + Maaf, ruangan ini tidak ditemukan. +\nMohon coba lagi nanti.%s + Belum diverifikasi · Aktivitas terakhir %1$s + Terverifikasi · Aktivitas terakhir %1$s + Tampilkan Semua (%1$d) + Tampilkan Detail + Verifikasi Sesi + Sesi belum diverifikasi + Sesi terverifikasi + Tipe perangkat tidak diketahui + Desktop + Web + Ponsel + Undangan + Coba + Ketuk kanan atas untuk melihat opsi untuk memberikan masukan. + Beri Masukan + Aplikasi obrolan aman untuk tim, teman, dan organisasi. Buat sebuah obrolan, atau bergabung ke ruangan yang sudah ada, untuk memulai. + Akses Space Anda (di kanan bawah) dengan lebih cepat dan lebih mudah dari sebelumnya. + Akses Space + Untuk membuat ${app_name} Anda lebih sederhana, fitur tab sekarang opsional. Kelola menggunakan menu kanan atas. + Selamat datang di tampilan yang baru! + Ini di mana pesan Anda yang belum dibaca akan ditampilkan, ketika Anda menerimanya. + Tidak ada untuk dilaporkan. + Selamat datang di ${app_name}, +\n%s. + Space adalah cara baru untuk mengelompokkan ruangan dan orang. Tambahkan ruangan yang sudah ada, atau buat yang baru, dengan tombol di kanan bawah. + %s +\nkelihatannya masih kosong. + + Pertimbangkan untuk mengeluarkan sesi lawas (%1$d hari atau lebih) yang Anda tidak gunakan lagi. + + Sesi yang tidak aktif + Verifikasi atau keluarkan sesi yang belum diverifikasi. + Sesi yang belum diverifikasi + Perbaiki keamanan akun Anda dengan mengikuti saran berikut. + Saran keamanan + + Tidak aktif selama %1$d+ hari (%2$s) + + Ini di mana permintaan dan undangan baru Anda akan berada. + Belum ada yang baru. + Space adalah cara baru untuk mengelompokkan ruangan dan orang. Buat sebuah space untuk memulai. + Belum ada space. + Tutup %s anak + Buka %s anak + Buat Space diff --git a/library/ui-strings/src/main/res/values-is/strings.xml b/library/ui-strings/src/main/res/values-is/strings.xml index 7818761145..d25d66bfba 100644 --- a/library/ui-strings/src/main/res/values-is/strings.xml +++ b/library/ui-strings/src/main/res/values-is/strings.xml @@ -193,7 +193,7 @@ Þema Afkóðunarvilla Heiti tækis - Auðkenni setu + Auðkenni setu Dulritunarlykill setu Flytja út Settu inn lykilsetningu diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 5dd17d5cbe..b7b0fe91af 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -430,7 +430,7 @@ Tema Errore di decriptazione Nome pubblico - ID sessione + ID sessione Chiave sessione Esporta le chiavi di crittografia E2E delle stanze Esporta le chiavi delle stanze @@ -2592,8 +2592,8 @@ Apri le impostazioni Tutte le chat Mostra tutte le sessioni (V2, WIP) - Per una maggiore sicurezza, verifica le tue sessioni e disconnetti quelle che non riconosci o che non usi più. - Altre sessioni + Per una maggiore sicurezza, verifica le tue sessioni e disconnetti quelle che non riconosci o che non usi più. + Altre sessioni Sessioni Apri elenco spazi Crea una nuova conversazione o stanza @@ -2610,4 +2610,53 @@ Esplora le stanze Crea una stanza Inizia una chat + Non verificata · Ultima attività %1$s + Verificata · Ultima attività %1$s + Vedi tutte (%1$d) + Vedi dettagli + Verifica la sessione + Sessione non verificata + Sessione verificata + Tipo di dispositivo sconosciuto + Desktop + Web + Mobile + Spiacenti, questa stanza non è stata trovata. +\nRiprova più tardi.%s + Inviti + Provalo + Tocca in alto a destra per vedere l\'opzione feedback. + Invia un feedback + Accedi ai tuoi spazi (in basso a destra) più velocemente e più facilmente che mai. + Accedi agli spazi + Per semplificare ${app_name}, le schede ora sono opzionali. Gestiscile usando il menu in alto a destra. + Benvenuti ad una nuova panoramica! + Qui è dove verranno mostrati i messaggi non letti, quando ne avrai qualcuno. + Niente da segnalare. + L\'app di chat tutto-in-uno per team, amici e organizzazioni. Inizia una conversazione o entra in una stanza esistente per cominciare. + Benvenuto/a in ${app_name}, +\n%s. + Gli spazi sono un modo nuovo di raggruppare stanze e persone. Aggiungi una stanza esistente, o creane una nuova usando il pulsante in basso a destra. + %s +\nsembra un po\' vuoto. + + Considera di disconnettere le sessioni vecchie (%1$d giorno o più) che non usi più. + Considera di disconnettere le sessioni vecchie (%1$d giorni o più) che non usi più. + + Sessioni inattive + Verifica o disconnetti le sessioni non verificate. + Sessioni non verificate + Migliora la sicurezza del tuo account seguendo questi consigli. + Consigli di sicurezza + + Inattivo da %1$d+ giorno (%2$s) + Inattivo da %1$d+ giorni (%2$s) + + Qui è dove troverai le nuove richieste e gli inviti. + Niente di nuovo. + Gli spazi sono un modo nuovo di raggruppare stanze e persone. Crea uno spazio per iniziare. + Ancora nessuno spazio. + Riduci contenuto di %s + Espandi contenuto di %s + Cambia spazio diff --git a/library/ui-strings/src/main/res/values-iw/strings.xml b/library/ui-strings/src/main/res/values-iw/strings.xml index 6d9533852b..ff19310c8e 100644 --- a/library/ui-strings/src/main/res/values-iw/strings.xml +++ b/library/ui-strings/src/main/res/values-iw/strings.xml @@ -542,7 +542,7 @@ יצא מפתחות חדר ייצא מפתחות חדר E2E מזהה מפתח - מזהה מושב + מזהה מושב שם ציבורי שגיאת פענוח ערכת נושא diff --git a/library/ui-strings/src/main/res/values-ja/strings.xml b/library/ui-strings/src/main/res/values-ja/strings.xml index b781e4d7f0..3e817e398c 100644 --- a/library/ui-strings/src/main/res/values-ja/strings.xml +++ b/library/ui-strings/src/main/res/values-ja/strings.xml @@ -197,7 +197,7 @@ これらは予期しない不具合が生じるかもしれない実験的機能です。慎重に使用してください。 メインアドレスとして設定 メインアドレスとしての設定を解除 - セッションID + セッションID 文字の大きさ とても小さい 小さい diff --git a/library/ui-strings/src/main/res/values-kab/strings.xml b/library/ui-strings/src/main/res/values-kab/strings.xml index a79b72efde..353fb99f53 100644 --- a/library/ui-strings/src/main/res/values-kab/strings.xml +++ b/library/ui-strings/src/main/res/values-kab/strings.xml @@ -291,7 +291,7 @@ Talqayt Tinarimin Asentel - Asulay n tqimit + Asulay n tqimit Tasarut n tɣimit Sifeḍ tisura n texxamt E2E Sifeḍ tisura n texxamt diff --git a/library/ui-strings/src/main/res/values-ko/strings.xml b/library/ui-strings/src/main/res/values-ko/strings.xml index ba0cbe5abd..37e8849fa8 100644 --- a/library/ui-strings/src/main/res/values-ko/strings.xml +++ b/library/ui-strings/src/main/res/values-ko/strings.xml @@ -431,7 +431,7 @@ 테마 암호 복호화 오류 공개 이름 - ID + ID 기기 키 종단간 암호화 방 키 내보내기 방 키 내보내기 diff --git a/library/ui-strings/src/main/res/values-lo/strings.xml b/library/ui-strings/src/main/res/values-lo/strings.xml index 1a9a2820b8..a92adb0225 100644 --- a/library/ui-strings/src/main/res/values-lo/strings.xml +++ b/library/ui-strings/src/main/res/values-lo/strings.xml @@ -909,7 +909,7 @@ ສົ່ງອອກກະແຈຫ້ອງ ສົ່ງອອກກະແຈຫ້ອງ E2E ລະຫັດລະບົບ - ID ລະບົບ + ID ລະບົບ ຊື່ສາທາລະນະ ການຖອດລະຫັດຜິດພາດ ຫົວຂໍ້ diff --git a/library/ui-strings/src/main/res/values-lt/strings.xml b/library/ui-strings/src/main/res/values-lt/strings.xml index 454bf8a4db..adfc70c36e 100644 --- a/library/ui-strings/src/main/res/values-lt/strings.xml +++ b/library/ui-strings/src/main/res/values-lt/strings.xml @@ -1,5 +1,5 @@ - + Naudotojo %s pakvietimas Jūs prisijungėte prie kambario %1$s prisijungė prie kambario @@ -447,4 +447,963 @@ %d praleistų balso skambučių Skambutis baigtas + ${app_name} reikia leidimo prieiti prie jūsų mikrofono, kad galėtumėte atlikti garso skambučius. + Baigiamas skambutis… + Nuotolinio ryšio pusėje nepavyko prisijungti. + Jokio atsakymo + Naudotojas, kuriam skambinote, yra užimtas. + Naudotojas užimtas + Sulaikėte skambutį + %s sulaikė skambutį + Sulaikyti + Tęsti + Balso skambutis su %s + Vaizdo skambutis su %s + Vaizdo skambutis vyksta… + Skambutis vyksta… + Įeinantis balso skambutis + Įeinantis vaizdo skambutis + + Praleistas vaizdo skambutis + %d praleisti vaizdo skambučiai + %d praleistų vaizdo skambučių + + Skambutis skamba… + Jungiamasi prie skambučio… + Pasirinkite skambučių melodiją: + Įeinančio skambučio melodija + Įeinantiems skambučiams naudoti numatytąją ${app_name} melodiją + Prieš pradedant skambutį prašyti patvirtinimo + Užkirsti kelią atsitiktiniam skambučiui + Mažas + Vidutinis + Didelis + Originalas + + %d narystės pokytis + %d narystės pokyčiai + %d narystės pokyčių + + Prašome paleisti ${app_name} kitame įrenginyje, kuris gali iššifruoti žinutę, kad galėtų išsiųsti raktus į šią sesiją. + Pakartotinai paprašykite šifravimo raktų iš kitų seansų. + Išsiųsta per daug užklausų + Nebuvo tinkamo JSON + Klaidingas JSON + Neautorizuotas, trūksta galiojančių tapatumo duomenų + SSL klaida. + SSL klaida: bendrakeleivio tapatybė nepatvirtinta. + Pasirinkti namų serverį + Nepavyko pasiekti namų serverio URL adresu %s. Patikrinkite nuorodą arba pasirinkite namų serverį rankiniu būdu. + Nepavyko pasiekti namų serverio šiuo URL adresu, prašome jį patikrinti + Tai nėra galiojantis \"Matrix\" serverio adresas + Prašome įvesti tinkamą URL adresą + Peržiūrėkite ir sutikite su šio namų serverio taisyklėmis: + %1$s išėjo iš kambario. Priežastis: %2$s + Prisijungėte. Priežastis: %1$s + %1$s prisijungė. Priežastis: %2$s + Prisijungėte prie kambario. Priežastis: %1$s + %1$s prisijungė prie kambario. Priežastis: %2$s + Siunčiama žinutė… + Žinutė išsiųsta + - Kai kurie naudotojai nebeignoruojami + ${app_name} turi išvalyti talpyklą, kad ji būtų atnaujinta dėl šios priežasties: +\n%s +\n +\nAtkreipkite dėmesį, kad atlikus šį veiksmą programa bus paleista iš naujo ir tai gali šiek tiek užtrukti. + Pradinio sinchronizavimo užklausa + Pradinė sinchronizacija: +\nImportuojame paskyros duomenis + Pradinė sinchronizacija: +\nImportuojame išeitus kambarius + Pradinė sinchronizacija: +\nImportuojame kambarių kvietimus + Pradinė sinchronizacija: +\nĮkeliame jūsų pokalbius +\nJei prisijungėte prie daugybės kambarių, tai gali užtrukti + Pradinė sinchronizacija: +\nImportuojame kambarius + Pradinė sinchronizacija: +\nImportuojame kriptografija + Pradinė sinchronizacija: +\nImportuojame paskyrą… + Pradinė sinchronizacija: +\nLaukiame serverio atsakymo… + Pradinė sinchronizacija: +\nAtsisiunčiame duomenis… + Tuščias kambarys (buvo %s) + Tuščias kambarys + + %1$s, %2$s, %3$s ir %4$d kitas + %1$s, %2$s, %3$s ir %4$d kiti + %1$s, %2$s, %3$s ir %4$d kitų + + %1$s, %2$s, %3$s ir %4$s + %1$s, %2$s ir %3$s + %1$s ir %2$s + Kvietimas į kambarį + Telefono numeris + El. pašto adresas + Jums neleidžiama prisijungti prie šio kambario + Sukurti kambarį + Naršyti kambarius + Jūs atnaujinote čia. + El. paštas nepatvirtintas, patikrinkite savo pašto dėžutę + Nepavyko patvirtinti el. pašto adreso: įsitikinkite, kad paspaudėte el. laiške esančią nuorodą + Šis namų serveris norėtų įsitikinti, kad nesate robotas + Pamiršote slaptažodį\? + Šis telefono numeris jau yra įrašytas. + Šis el. pašto adresas jau yra įrašytas. + Tai neatrodo kaip tinkamas el. pašto adresas + Neteisingas naudotojo vardas ir (arba) slaptažodis + Pateikti + Prisijungimas vienkartiniu prisijungimu + Prisijungti + Atsiprašome, nerastos jokios išorinės programos šiam veiksmui atlikti. + Šiuo metu nėra įjungti jokie lipdukų paketai. +\n +\nAr norite pridėti keletą dabar\? + Naudoti kaip numatytąjį ir daugiau neklausti + Filmuoti + Fotografuoti + Fotografuoti arba filmuoti + Siųsti lipduką + Siųsti failus + Sustabdyti ekrano bendrinimą + Bendrinti ekraną + Įjungti HD + Išjungti HD + Atgalinė + Priekinė + Perjungti kamerą + Pasirinkite garso įrenginį + Kvietimai + A - Z + Veikla + Rikiuoti pagal + Rodyti naujausius + Rodyti filtrus + Išdėstymo parinktys + Kitas + min + val + %1$s pakeitė alternatyvius šio kambario adresus. + + Pašalinote alternatyvų šio kambario adresą %1$s. + Pašalinote alternatyvius šio kambario adresus %1$s. + Pašalinote alternatyvius šio kambario adresus %1$s. + + + %1$s pašalino alternatyvų šio kambario adresą %2$s. + %1$s pašalino alternatyvius šio kambario adresus %2$s. + %1$s pašalino alternatyvius šio kambario adresus %2$s. + + + Pridėjote alternatyvų šio kambario adresą %1$s. + Pridėjote alternatyvius šio kambario adresus %1$s. + Pridėjote alternatyvius šio kambario adresus %1$s. + + + %1$s pridėjo alternatyvų šio kambario adresą %2$s. + %1$s pridėjo alternatyvius šio kambario adresus %2$s. + %1$s pridėjo alternatyvius šio kambario adresus %2$s. + + Pašalinote pagrindinį šio kambario adresą. + %1$s pašalino pagrindinį šio kambario adresą. + Nustatėte pagrindinį šio kambario adresą į %1$s. + %1$s nustatė pagrindinį šio kambario adresą į %2$s. + Pridėjote %1$s ir pašalinote %2$s kaip šio kambario adresus. + %1$s pridėjo %2$s ir pašalino %3$s kaip šio kambario adresus. + + Pašalinote %1$s kaip šio kambario adresą. + Pašalinote %1$s iš šio kambario adresų. + Pašalinote %1$s iš šio kambario adresų. + + + %1$s pašalino %2$s kaip šio kambario adresą. + %1$s pašalino %2$s iš šio kambario adresų. + %1$s pašalino %2$s iš šio kambario adresų. + + + Pridėjote %1$s kaip šio kambario adresą. + Pridėjote %1$s kaip šio kambario adresus. + Pridėjote %1$s kaip šio kambario adresus. + + + %1$s pridėjo %2$s kaip šio kambario adresą. + %1$s pridėjo %2$s kaip šio kambario adresus. + %1$s pridėjo %2$s kaip šio kambario adresus. + + Atšaukėte %1$s kvietimą. Priežastis: %2$s + %1$s atšaukė %2$s kvietimą. Priežastis: %3$s + Priėmėte %1$s kvietimą. Priežastis: %2$s + %1$s priėmė %2$s kvietimą. Priežastis: %3$s + Jūs užblokavote %1$s. Priežastis: %2$s + %1$s užblokavo %2$s. Priežastis: %3$s + Atblokavote %1$s. Priežastis: %2$s + %1$s atblokavo %2$s. Priežastis: %3$s + Pašalinote %1$s. Priežastis: %2$s + %1$s pašalino %2$s. Priežastis: %3$s + Kvietimą atmetėte. Priežastis: %1$s + %1$s atmetė kvietimą. Priežastis: %2$s + Išėjote. Priežastis: %1$s + %1$s išėjo. Priežastis: %2$s + Išėjote iš kambario. Priežastis: %1$s + Visi pokalbiai + Matricos klaida + Nepavyksta išsiųsti žinutės + Siuntėjo įrenginys neatsiuntė mums šios žinutės raktų. + ** Nepavyksta iššifruoti: %s ** + %1$s nuo %2$s iki %3$s + %1$s pakeitė %2$s galios lygį. + Pakeitėte %1$s galios lygį. + Pasirinktinis + Pasirinktinis (%1$d) + Standartinis + Moderatorius + Adminas + Pakeitėte %1$s valdiklį + %1$s pakeitė %2$s valdiklį + Pašalinote %1$s valdiklį + %1$s pašalino %2$s valdiklį + Pridėjote %1$s valdiklį + %1$s pridėjo %2$s valdiklį + %1$s išsiuntė kvietimą %2$s prisijungti prie kambario + %1$s atšaukė %2$s pakvietimą prisijungti prie kambario + Priėmėte kvietimą į %1$s + %1$s priėmė kvietimą į %2$s + Atšaukėte kvietimą %1$s + %1$s atšaukė %2$s kvietimą + Atšaukėte %1$s pakvietimą prisijungti prie kambario + Pakeitimų nėra. + • Serveriai atitinkantys %s buvo pašalinti iš leidžiamų sąrašo. + • Serveriai atitinkantys %s dabar yra leidžiami. + • Serveriai atitinkantys %s buvo pašalinti iš draudimų sąrašo. + • Serveriai atitinkantys %s dabar yra uždrausti. + • Serveriai atitinkantys %s yra leidžiami. + • Serveriai atitinkantys %s yra uždrausti. + Siųsti m.room.server_acl įvykius + Užblokuoti naudotoją + Naudotojas bus pašalintas iš šio kambario. +\n +\nKad jis negalėtų prisijungti dar kartą, turėtumėte jį užblokuoti. + Pašalinimo priežastis + Pašalinti naudotoją + Ar tikrai norite atšaukti kvietimą šiam naudotojui\? + Atšaukti kvietimą + Nebeignoruoti + Nebeignoruojant šio naudotojo, vėl bus rodomos visos jo žinutės. + Nebeignoruoti naudotojo + Ignoruodami šį naudotoją nebematysite jo žinučių bendruose kambariuose. +\n +\nŠį veiksmą bet kada galite atšaukti bendruosiuose nustatymuose. + Ignoruoti naudotoją + Pažeminti + Negalėsite atšaukti šio pakeitimo, nes pažeminsite save, o jei esate paskutinis privilegijuotas naudotojas kambaryje, bus neįmanoma susigrąžinti privilegijų. + Nuleisti save į žemesnes pareigas\? + Šio pakeitimo atšaukti negalėsite, nes padidinsite naudotojo galią, kad jis turėtų tokį patį galios lygį, kaip ir jūs pats. +\nAr esate tikri\? + Paminėti + Pašalinti iš pokalbio + Atšaukti kvietimą + Tiesioginiai pokalbiai + Šis kambarys nėra viešas. Negalėsite vėl prisijungti be kvietimo. + Ar tikrai norite palikti kambarį\? + Palikti kambarį + + %d narys + %d nariai + %d narių + + Pereiti prie neskaitytų + Nariai + Suteikite leidimą prieiti prie savo kontaktų. + Jei norite nuskaityti QR kodą, turite leisti kameros prieigą. + ${app_name} reikia leidimo prieiti prie jūsų kameros ir mikrofono, kad galėtumėte atlikti vaizdo skambučius. +\n +\nKad galėtumėte skambinti, kituose iškylančiuose languose leiskite prieigą. + Čia bus pateikiamos naujos užklausos ir kvietimai. + Nieko naujo. + Pradėti pokalbį + • Serveriai atitinkantys IP dabar yra užblokuoti. + • Serveriai atitinkantys IP dabar yra leidžiami. + + %d serverių ACL pakeitimas + %d serverių ACL pakeitimai + %d serverių ACL pakeitimų + + Pakeitėte serverių ACL šiam kambariui. + %s pakeitė serverių ACL šiam kambariui. + • Serveriai atitinkantys IP yra užblokuoti. + • Serveriai atitinkantys IP yra leidžiami. + Nustatėte serverių ACL šiam kambariui. + %s nustatė serverių ACL šiam kambariui. + Išbandyti + Bakstelėkite viršuje dešinėje, kad pamatytumėte atsiliepimų parinktį. + Pateikite atsiliepimus + Pasiekti erdves + Pasiekite erdves (apačioje dešinėje) greičiau ir paprasčiau nei bet kada anksčiau. + Siekiant supaprastinti jūsų ${app_name}, skirtukai dabar yra neprivalomi. Tvarkykite juos naudodami viršutinį dešinės pusės meniu. + Sveiki atvykę į naują vaizdą! + Čia bus rodomos jūsų neperskaitytos žinutės, kai jų turėsite. + Nėra apie ką pranešti. + \"viskas viename\" saugi pokalbių programėlė komandoms, draugams ir organizacijoms. Sukurkite pokalbį arba prisijunkite prie esamo kambario ir pradėkite. + Sveiki atvykę į ${app_name}, +\n%s. + Erdvės - tai naujas kambarių ir žmonių grupavimo būdas. Pridėkite esamą kambarį arba sukurkite naują naudodami apatinį dešinįjį mygtuką. + %s +\natrodo šiek tiek tuščia. + + Apsvarstykite galimybę atsijungti iš senų sesijų (%1$d diena ar daugiau), kurių nebenaudojate. + Apsvarstykite galimybę atsijungti iš senų sesijų (%1$d dienos ar daugiau), kurių nebenaudojate. + Apsvarstykite galimybę atsijungti iš senų sesijų (%1$d dienų ar daugiau), kurių nebenaudojate. + + Neaktyvios sesijos + Patvirtinkite nepatvirtintas sesijas arba atjunkite jas. + Nepatvirtintos sesijos + Pagerinkite savo paskyros saugumą laikydamiesi šių rekomendacijų. + Saugumo rekomendacijos + + Neaktyvus %1$d+ dieną (%2$s) + Neaktyvus %1$d+ dienas (%2$s) + Neaktyvus %1$d+ dienų (%2$s) + + Nepatvirtinta · Paskutinė veikla %1$s + Patvirtinta · Paskutinė veikla %1$s + Peržiūrėti visas (%1$d) + Peržiūrėti detales + Patvirtinti sesiją + Nepatvirtinta sesija + Patvirtinta sesija + Nežinomas įrenginio tipas + Stalinis kompiuteris + Naršyklė + Mobilus + + %d žinutė pašalinta + %d žinutės pašalintos + %d žinučių pašalinta + + Įjungti vietos bendrinimą + Atkreipkite dėmesį, kad tai yra laboratorinė funkcija, kuri įgyvendinama laikinai. Tai reiškia, kad negalėsite ištrinti savo buvimo vietos istorijos, o pažengę naudotojai galės matyti jūsų buvimo vietos istoriją net tada, kai nustosite bendrinti savo tiesioginę buvimo vietą su šiuo kambariu. + Tiesioginės buvimo vietos bendrinimas + Dabartiniai vartai: %s + Vartai + Nepavyksta rasti galinio taško. + Dabartinis galinis taškas: %s + Galinis taškas + Šiuo metu naudojamas %s. + Metodas + + Rastas %d metodas. + Rasti %d metodai. + Rasti %d metodų. + + Nerastas joks kitas metodas, išskyrus foninį sinchronizavimą. + Nerastas joks kitas būdas, išskyrus Google Play paslaugas. + Galimi metodai + Pranešimo metodas + Foninis sinchronizavimas + Google Paslaugos + Pasirinkite, kaip gauti pranešimus + Vyksta ekrano bendrinimas + ${app_name} Ekrano bendrinimas + Kambario pranešimas + Naudotojai + Pranešti visam kambariui + + %1$d daugiau + %1$d daugiau + %1$d daugiau + + Rodyti mažiau + Bendrinti vietą + Kurti apklausą + Atidaryti kontaktus + Siųsti lipduką + Įkelti failą + Reikalingas atnaujinimas + Atnaujinti + Būkite kantrūs, tai gali užtrukti. + Prisijungti prie pakaitinio kambario + Nepavadintas kambarys + Jūs esate vienintelis šios erdvės administratorius. Jei ją paliksite, tai reikš, kad niekas jos nebekontroliuos. + Negalėsite prisijungti vėl, nebent būsite pakviestas iš naujo. + Jūs esate vienintelis čia esantis asmuo. Jei paliksite, ateityje niekas, įskaitant jus, negalės prisijungti. + Ar tikrai norite palikti %s\? + Nepalikti nė vieno + Palikti visus + Dalykai šioje erdvėje + Vistiek prisijungti + Kol kas praleisti + Baigti nustatyti atradimą. + Šiuo metu šis pseudonimas neprieinamas. +\nPabandykite vėliau arba paprašykite kambario administratoriaus patikrinti, ar turite prieigą. + Atradimas (%s) + Užbaigti sąranka + Kvieskite el. paštu, ieškokite kontaktų ir daugiau… + Jie nebus %s dalis + Tik į šį kambarį + Šiuo metu nenaudojate tapatybės serverio. Norėdami pakviesti komandos draugus ir būti jų atrandami, sukonfigūruokite jį toliau. + Prisijungti prie erdvės + Sukurti erdvę + Prisijunkite prie mano erdvės %1$s %2$s + Jie galės tyrinėti %s + Pakvietimas į %s + Kviesti žmones į savo erdvę + Aprašymas + Kuriama erdvė… + Atsitiktinis + Bendra + Sukurkime kiekvienai iš jų po kambarį. Vėliau galite pridėti ir daugiau, įskaitant jau esamus. + Su kokiais dalykais dirbate\? + Užtikrinkite, kad prieigą prie %s kompanijos turėtų tinkami žmonės. Vėliau galite pakviesti daugiau. + Kas yra jūsų komandos draugai\? + Mes sukursime joms kambarius. Vėliau galėsite pridėti ir daugiau. + Kokias diskusijas norite turėti %s\? + Suteikite jai pavadinimą, kad galėtumėte tęsti. + Pridėkite šiek tiek detalių, kad žmonės galėtų ją atpažinti. Jas galite keisti bet kuriuo metu. + Įtraukite keletą detalių, kurios padės išsiskirti. Jas galite keisti bet kuriuo metu. + Sukurti erdvę + Privati erdvė jums & jūsų komandos draugams + Aš ir komandos draugai + Privati erdvė kambariams organizuoti + Tik aš + Užtikrinkite, kad prieigą prie %s turėtų tinkami asmenys. + Su kuo dirbate\? + Norėdami prisijungti prie esamos erdvės, turite gauti kvietimą. + Galite tai pakeisti vėliau + Kokio tipo erdvę norite sukurti\? + Jūsų privati erdvė + Jūsų vieša erdvė + Pridėti erdvę + Privati erdvė + Vieša erdvė + Prisijungti prie erdvės su nurodytu id + Pridėti prie nurodytos erdvės + Sukurti erdvę + Neteisingas naudotojo vardas ir (arba) slaptažodis. Įvestas slaptažodis prasideda arba baigiasi tarpais, patikrinkite jį. + Kuriama erdvė… + Erdvės adresas + Negalima atidaryti šios nuorodos: bendruomenės buvo pakeistos erdvėmis + Atidaryti erdvių sąrašą + Naudojate erdvių beta versiją. Jūsų atsiliepimai padės parengti kitas versijas. Jūsų platforma ir naudotojo vardas bus pažymėti, kad galėtume kuo geriau pasinaudoti jūsų atsiliepimais. + Atsiliepimai apie erdves + Sukurti naują erdvę + Kitos erdvės ar kambariai, apie kuriuos galbūt nežinote + Erdvė, apie kurią žinote, kurioje yra šis kambarys + Bakstelėkite, kad redaguoti erdves + Pasirinkti erdves + Nuspręskite, kurios erdvės gali prieit prie šio kambario. Jei pasirinkta erdvė, jos nariai galės rasti kambario pavadinimą ir prie jo prisijungti. + Erdvės, kurios gali pasiekti + Leisti erdvės nariams rasti ir pasiekti. + Erdvės %s nariai gali rasti, peržiūrėti ir prisijungti. + Kiekvienas, esantis erdvėje, kurioje yra šis kambarys, gali jį rasti ir prie jo prisijungti. Tik šio kambario administratoriai gali jį įtraukti į erdvę. + Tik erdvės nariams + Bet kas gali rasti šią erdvę ir prisijungti + Peržiūrėti ir valdyti šios erdvės adresus. + Erdvės adresai + Erdvės prieiga + + %1$s ir %2$d kitas + %1$s ir %2$d kiti + %1$s ir %2$d kitų + + Atnaujinti erdvę + Keisti erdvės pavadinimą + Įjungti erdvės šifravimą + Keisti erdvės pagrindinį adresą + Keisti erdvės avatarą + Neturite leidimo atnaujinti roles, reikalingas įvairioms šios erdvės dalims keisti + Pasirinkite roles, reikalingas įvairioms šios erdvės dalims keisti + Peržiūrėkite ir atnaujinkite roles, reikalingas įvairioms erdvės dalims keisti. + Erdvės leidimai + Atblokavus naudotoją, jis vėl galės prisijungti prie erdvės. + Užblokavus naudotoją, jis bus pašalintas iš šios erdvės ir negalės prisijungti dar kartą. + Naudotojas bus pašalintas iš šios erdvės. +\n +\nKad jis negalėtų prisijungti dar kartą, turėtumėte jį užblokuoti. + Erdvės + Erdvės - tai naujas kambarių ir žmonių grupavimo būdas. Sukurkite erdvę ir pradėkite. + Erdvių dar nėra. + Erdvės + Keisti erdvę + Atsarginė kopija turi galiojantį parašą iš nepatvirtintos sesijos %s + Atsarginė kopija turi galiojantį parašą iš patvirtintos sesijos %s. + Atsarginė kopija turi galiojantį šios sesijos parašą. + Atsarginė kopija turi galiojantį šio naudotojo parašą. + Atsarginė kopija turi nežinomos sesijos parašą su ID %s. + Jūsų raktų atsarginės kopijos iš šios sesijos nedaromos. + Šioje sesijoje raktų atsarginė kopija nėra aktyvi. + Šiai sesijai teisingai nustatyta atsarginė raktų kopija. + Ištrinti atsarginę kopiją + Atkurti iš atsarginės kopijos + Nepavyko gauti naujausios atkūrimo raktų versijos (%s). + + %d naujas raktas buvo pridėtas prie šios sesijos. + %d nauji raktai buvo pridėti prie šios sesijos. + %d naujų raktų buvo pridėta prie šios sesijos. + + + Atkurta atsarginė kopija su %d raktu. + Atkurta atsarginė kopija su %d raktais. + Atkurta atsarginė kopija su %d raktų. + + Atkurta atsarginė kopija %s ! + Atsarginės kopijos nepavyko iššifruoti naudojant šį atkūrimo raktą: patikrinkite, ar įvedėte teisingą atkūrimo raktą. + Įveskite atkūrimo raktą + Atrakinti istoriją + Importuojami raktai… + Atsisiunčiami raktai… + Apskaičiuojame atkūrimo raktą… + Atkuriama atsarginė kopija: + Atsarginės kopijos nepavyko iššifruoti naudojant šią slaptafrazę: patikrinkite, ar įvedėte teisingą atkūrimo slaptafrazę. + Pametėte atkūrimo raktą\? Galite nustatyti naują nustatymuose. + Įvesti atkūrimo raktą + Naudoti atkūrimo raktą, kad atrakinti užšifruotų žinučių istoriją + Nežinote savo atkūrimo slaptafrazės, galite %s. + naudokite savo atkūrimo raktą + Naudokite atkūrimo slaptafrazę, kad atrakintumėte užšifruotų žinučių istoriją + Gauname atsarginę versiją… + Jei atsijungsite arba prarasite šį prietaisą, galite prarasti prieigą prie savo žinučių. + Ar esate tikri\? + Netikėta klaida + Atkūrimo raktas + Generuojame atkūrimo raktą naudojant slaptafrazę, šis procesas gali užtrukti kelioliką sekundžių. + Bendrinti atkūrimo raktą su… + Prašome pasidaryti kopiją + Sustabdyti + Pakeisti + Atrodo, kad jau esate sukūrę atsarginę raktų kopiją iš kitos sesijos. Ar norite ją pakeisti kuriama\? + Jūsų namų serveryje jau yra atsarginė kopija + Atkūrimo raktas buvo išsaugotas. + Įrašyti kaip failą + Bendrinti + Išsaugoti atkūrimo raktą + Padariau kopiją + Baigta + Atkūrimo raktą laikykite labai saugioje vietoje, pvz., slaptažodžių tvarkyklėje (arba seife) + Atkūrimo raktas yra apsauginis tinklas - juo galite atkurti prieigą prie užšifruotų žinučių, jei pamiršite slaptafrazę. +\nAtkūrimo raktą laikykite labai saugioje vietoje, pvz., slaptažodžių tvarkyklėje (arba seife) + Jūsų raktų atsarginė kopija yra kuriama. + Sėkmė ! + (Išplėstinė) Nustatyti su atkūrimo raktu + Arba apsaugokite atsarginę kopiją naudodami atkūrimo raktą ir išsaugokite ją saugioje vietoje. + Atsarginės kopijos kūrimas + Nustatyti slaptafrazę + Jūsų namų serveryje išsaugosime šifruotą raktų kopiją. Apsaugokite atsarginę kopiją slaptafraze, kad ji būtų saugi. +\n +\nSiekiant maksimalaus saugumo, ji turėtų skirtis nuo jūsų paskyros slaptažodžio. + Apsaugokite atsarginę kopiją slaptafraze. + Eksportuoti raktus rankiniu būdu + (Išplėstiniai) + Pradėti naudoti raktų atsarginį kopijavimą + Užšifruotuose kambariuose siunčiamos žinutės yra apsaugotos šifravimu nuo galo iki galo. Tik jūs ir gavėjas (-ai) turite raktus, kad galėtumėte perskaityti šias žinutes. +\n +\nSaugiai kurkite atsargines raktų kopijas, kad jų neprarastumėte. + Niekada nepraraskite užšifruotų žinučių + Ištrinkite slaptafrazę, jei norite, kad ${app_name} sugeneruotų atkūrimo raktą. + Slaptafrazė yra per silpna + Įveskite slaptafrazę + Slaptafrazė nesutampa + Įvesti slaptafrazę + Patvirtinti slaptafrazę + Sukurti slaptafrazę + Nerastas galiojantis Google Play Paslaugų APK. Pranešimai gali neveikti tinkamai. + +%d + %1$s: %2$s + suskleisti + išplėsti + Atsiprašome, įvyko klaida + Jei norite toliau naudotis šia paslauga, prašome %s. + Prašome %s kad padidinti šią ribą. + Šis namų serveris pasiekė savo mėnesio aktyviųjų naudotojų limitą. + Šis namų serveris pasiekė mėnesio aktyviųjų naudotojų limitą, todėl kai kurie naudotojai negalės prisijungti. + Šis namų serveris viršijo vieną iš savo išteklių limitų. + Šis namų serveris viršijo vieną iš savo išteklių limitų, todėl kai kurie naudotojai negalės prisijungti. + kreipkitės į savo paslaugų administratorių + Spustelėkite čia, kad pamatytumėte senesnes žinutes + Šis kambarys yra kito pokalbio tęsinys + Pokalbis tęsiamas čia + Šis kambarys buvo pakeistas ir nebėra aktyvus. + Įveskite savo slaptažodį. + Įveskite naudotojo vardą. + Deaktyvuoti paskyrą + Prašau pamiršti visas mano išsiųstas žinutes, kai mano paskyra bus deaktyvuota (Įspėjimas: dėl to būsimi naudotojai matys nepilną pokalbių vaizdą) + Dėl to jūsų paskyra visam laikui taps netinkama naudoti. Negalėsite prisijungti ir niekas negalės iš naujo užregistruoti to paties naudotojo ID. Dėl to jūsų paskyra išeis iš visų kambarių, kuriuose dalyvauja, ir iš jūsų tapatybės serverio bus pašalinti jūsų paskyros duomenys. Šis veiksmas yra negrįžtamas. +\n +\nDeaktyvavus paskyrą pagal numatytuosius nustatymus nepamirštame jūsų išsiųstų žinučių. Jei norite, kad pamirštume jūsų žinutes, pažymėkite toliau esantį langelį. +\n +\nŽinučių matomumas Matrix sistemoje yra panašus į el. pašto matomumą. Mūsų jūsų žinučių užmiršimas reiškia, kad jūsų išsiųstomis žinutėmis nebus dalijamasi su jokiais naujais ar neregistruotais naudotojais, tačiau registruoti naudotojai, kurie jau turi prieigą prie šių žinučių, vis tiek turės prieigą prie jų kopijos. + Deaktyvuoti paskyrą + Peržiūrėti dabar + Norėdami toliau naudoti %1$s namų serverį, turite peržiūrėti ir sutikti su nuostatomis ir sąlygomis. + Avataras + Priežastis: %1$s + %2$s jus užblokavo iš %1$s + %2$s jus pašalino iš %1$s + Pakviestas + Kambariai + Pradžia + Sukurti + Šifruota žinutė + Triukšmingas + Tylus + Jūs neturite leidimo tai daryti šiame kambaryje. + Jūs nesate šiame kambaryje. + Pridėti Matrix programėlių + Trūksta reikalingo parametro. + Kambarys %s nėra matomas. + Blokuoti visus + Leisti + Kambario ID + Naudoti mikrofoną + Naudoti kamerą + Tvarkyti integracijas + Jūsų nepatvirtinta sesija \'%s\' prašo šifravimo raktų. + Nauja sesija prašo šifravimo raktų. +\nSesijos pavadinimas: %1$s +\nPaskutinį kartą matyta: %2$s +\nJei neprisijungėte prie kitos sesijos, ignoruokite šią užklausą. + Pridėjote naują sesiją \'%s\', kuri prašo šifravimo raktų. + Nepatvirtinta sesija prašo šifravimo raktų. +\nSesijos pavadinimas: %1$s +\nPaskutinį kartą matyta: %2$s +\nJei neprisijungėte prie kitos sesijos, ignoruokite šią užklausą. + Nustatyti naudotojo galios lygį + Nustoja ignoruoti naudotoją ir rodo jo žinutes nuo dabar + ignoruoja naudotoją, slepiant jo žinutes nuo jūsų + Atblokuoja naudotoją su nurodytu id + Užblokuoja naudotoją su nurodytu id + Rodo veiksmą + Prisijungia prie kambario su nurodytu adresu + Pakviečia naudotoją su nurodytu id į šį kambarį + Nustato kambario pavadinimą + Markdown buvo išjungtas. + Markdown buvo įjungtas. + Rodo informaciją apie naudotoją + Pakeičia šio kambario avatarą + Pakeičia jūsų rodomą slapyvardį tik šiame kambaryje + Pakeičia jūsų avatarą tik šiame kambaryje + Pakeičia jūsų rodomą slapyvardį + Pašalina naudotoją su nurodytu id iš šio kambario + Nustatyti kambario temą + Palikti kambarį + Neatpažinta komanda: %s + Pradėti patvirtinimą + Komandos klaida + Ignoruoti + Bendrinti + Komanda \"%s\" atpažįstama, bet nepalaikoma temose. + Komandai \"%s\" reikia daugiau parametrų arba kai kurie parametrai yra neteisingi. + + %d pasirinktas + %d pasirinkti + %d pasirinktų + + Keisti temą + Atnaujinti kambarį + Numatyta rolė + Neturite leidimo atnaujinti roles, reikalingas įvairioms kambario dalims keisti + Pasirinkite roles, reikalingas įvairioms kambario dalims keisti + Leidimai + Peržiūrėti ir atnaujinti roles, reikalingas įvairioms kambario dalims keisti. + Kambario leidimai + Sertifikatą priimkite tik tuo atveju, jei serverio administratorius yra paskelbęs antspaudą, atitinkantį pirmiau nurodytą. + Sertifikatas pakeistas iš anksčiau patikimo į nepatikimą. Serveris galėjo atnaujinti savo sertifikatą. Kreipkitės į serverio administratorių dėl numatyto antspaudo. + Sertifikatas pakeistas iš to, kuriuo pasitikėjo jūsų telefonas. Tai LABAI NEĮPRASTA. Rekomenduojama NEPATVIRTINTI šio naujo sertifikato. + Jei serverio administratorius nurodė, kad to tikimasi, įsitikinkite, kad toliau pateiktas antspaudas atitinka jo pateiktą antspaudą. + Tai gali reikšti, kad kažkas piktavališkai perima jūsų duomenų srautą arba kad telefonas nepasitiki nuotolinio serverio pateiktu sertifikatu. + Nepavyko patvirtinti nuotolinio serverio tapatybės. + Antspaudas (%s): + Ignoruoti + Nepasitikėti + Pasitikėti + + %d nauja žinutė + %d naujos žinutės + %d naujų žinučių + + Šifravimas buvo neteisingai sukonfigūruotas, todėl negalite siųsti žinučių. Spustelėkite, kad atidarytumėte nustatymus. + Šifravimas buvo neteisingai sukonfigūruotas, todėl negalite siųsti žinučių. Susisiekite su administratoriumi, kad būtų atkurta galiojanti šifravimo būsena. + Jūs neturite leidimo rašyti šiame kambaryje. + %1$s, %2$s ir kiti + %1$s ir %2$s + %1$s & %2$s & kiti rašo… + %1$s & %2$s rašo… + %s rašo… + Atblokavus naudotoją, jis vėl galės prisijungti prie kambario. + Užblokavus naudotoją, jis bus pašalintas iš šio kambario ir negalės prisijungti dar kartą. + Atblokuoti naudotoją + Priežastis užblokavimui + Išplėstiniai + Kita + Ignoruojami naudotojai + Naudotojo nustatymai + Išvalyti medijos talpyklą + Išvalyti talpyklą + Saugoti mediją + Privatumo politika + Autorinės teisės + Trečiųjų šalių pastabos + Terminai ir sąlygos + + %d sekundė + %d sekundės + %d sekundžių + + Uždelsimas tarp kiekvieno sinchronizavimo + Sinchronizavimo užklausos laiko limitas + Paleisti sistemos paleidimo metu + Kai programėlė yra fone, apie gautus pranešimus nebūsite informuojami. + Nėra foninio sinchronizavimo + ${app_name} sinchronizuosis fone periodiškai tiksliai nustatytu laiku (galima konfigūruoti). +\nTai turės įtakos radijo ryšio ir baterijos naudojimui, bus rodomas nuolatinis pranešimas, kad ${app_name} klausosi įvykių. + Optimizuotas realiajam laikui + ${app_name} bus sinchronizuojama fone taip, kad būtų tausojami riboti įrenginio ištekliai (akumuliatorius). +\nPriklausomai nuo įrenginio išteklių būklės, operacinė sistema gali atidėti sinchronizavimą. + Optimizuotas akumuliatoriui + Foninio sinchronizavimo režimas + Foninis sinchronizavimas + Mobiliuosiuose įrenginiuose negausite pranešimų apie užšifruotuose kambariuose esančius paminėjimus ir raktažodžius. + Kambario atnaujinimai + Boto žinutės + Kvietimai skambinti + Kvietimai į kambarį + Raktažodžiai + \@kambarys + Šifruotos grupių žinutės + Grupių žinutės + Šifruotos tiesioginės žinutės + Tiesioginės žinutės + Mano naudotojo vardas + Mano rodomas vardas + Žinutės, kuriose yra @room + Boto išsiųstos žinutės + Kai mane pakviečia į kambarį + Žinutės grupiniuose pokalbiuose + Žinutės pokalbiuose vienas su vienu + Žinutės, kuriose yra mano naudotojo vardas + Žinutės, kuriose yra mano rodomas vardas + Kai kambariai atnaujinami + Šifruotos žinutės grupiniuose pokalbiuose + Šifruotos žinutės pokalbiuose vienas su vienu + Pasirinkti LED spalvą, vibraciją, garsą… + Tyliųjų pranešimų konfigūravimas + Skambučių pranešimų konfigūravimas + Triukšmingų pranešimų konfigūravimas + Įjungti pranešimus šiai sesijai + Įjungti pranešimus šiai paskyrai + Pranešimo garsas + Ignoruoti optimizavimą + Jei naudotojas kurį laiką palieka prietaisą atjungtą nuo elektros tinklo ir nejudantį, su išjungtu ekranu, prietaisas įjungia \"Doze\" režimą. Tai neleidžia programoms prisijungti prie tinklo ir atideda jų darbus, sinchronizavimą ir standartinius žadintuvus. + Akumuliatoriaus optimizavimas neįtakoja ${app_name}. + Akumuliatoriaus optimizavimas + Išjungti apribojimus + Įjungti foniniai apribojimai ${app_name}. +\nDarbas, kurį programa bando atlikti, bus agresyviai ribojamas, kol ji yra fone, ir tai gali turėti įtakos pranešimams. +\n%1$s + Fono apribojimai išjungti ${app_name}. Šis testas turėtų būti atliekamas naudojant mobiliuosius duomenis (be WIFI). +\n%1$s + Patikrinti fono apribojimus + Įjungti paleidimą sistemos paleidimo metu + Paslauga nebus paleista iš naujo paleidus įrenginį, pranešimų negausite, kol vieną kartą nebus atidaryta ${app_name}. + Paslauga bus paleista iš naujo paleidus įrenginį. + Paleisti sistemos paleidimo metu + Pranešimas buvo paspaustas! + Spustelėkite pranešimą. Jei pranešimo nematote, patikrinkite sistemos nustatymus. + Pranešimo rodymas + Jūs žiūrite pranešimą! Spausk ant manęs! + Kai kurie pranešimai yra išjungti pasirinktiniuose nustatymuose. + Atkreipkite dėmesį, kad kai kurie pranešimų tipai nustatyti kaip tylūs (pranešimas bus be garso). + Pasirinktiniai nustatymai. + Šioje sesijoje pranešimai neįjungti. +\nPatikrinkite ${app_name} nustatymus. + Šioje sesijoje pranešimai yra įjungti. + Sesijos nustatymai. + Pranešimai jūsų paskyroje yra išjungti. +\nPatikrinkite paskyros nustatymus. + Jūsų paskyroje pranešimai yra įjungti. + Paskyros nustatymai. + Atidaryti nustatymus + Sistemos nustatymuose pranešimai yra išjungti. +\nPatikrinkite sistemos nustatymus. + Pranešimai yra įjungti sistemos nustatymuose. + Sistemos nustatymai. + Vienas ar daugiau testų nepavyko, pateikite pranešimą apie klaidą ir padėkite mums ją ištirti. + Vienas ar daugiau testų nepavyko, išbandykite siūlomą (-us) pataisymą (-us). + Pagrindinė diagnostika yra gera. Jei vis dar negaunate pranešimų, pateikite pranešimą apie klaidą ir padėkite mums ją ištirti. + Vykdoma… (%1$d iš %2$d) + Atlikti bandymus + Trikčių diagnostika + Pranešimų trikčių šalinimas + Raktažodžiai negali turėti \'%s\' + Raktažodžiai negali prasidėti su \'.\' + Pridėti naują raktažodį + Jūsų raktažodžiai + Praneškite man apie + Kita + Paminėjimai ir raktažodžiai + Numatyti pranešimai + Įjungti pranešimus el. paštu %s + Norėdami gauti pranešimą el. paštu, susiekite el. paštą su savo Matrix paskyra + Pranešimas el. paštu + Pranešimo svarba pagal įvykį + Išplėstiniai pranešimų nustatymai + Įsitikinkite, kad paspaudėte jums atsiųstame el. laiške esančią nuorodą. + Pašalinti %s\? + Telefono numeriai + Prie jūsų paskyros nepridėtas joks el. paštas + El. pašto adresai + Rodyti programos informaciją sistemos nustatymuose. + Programos informacija + Pridėti telefono numerį + Prie jūsų paskyros nepridėtas joks telefono numeris + Pridėti el. pašto adresą + Rodomas vardas + Profilio nuotrauka + Sesija buvo atjungta! + %1$s ir %2$s + Nėra rezultatų + Filtruoti užblokuotus narius + Filtruoti kambario narius + Ieškoti + Kambarys buvo paliktas! + Pridėti prie pagrindinio ekrano + Nėra + Tik paminėjimai & raktažodžiai + Visos žinutės + Filtruoti temas kambaryje + Temos artėja prie beta versijos 🎉 + Siųsti nuotraukas ir vaizdo įrašus + Atidaryti fotoaparatą + Rodyti žinučių burbulus + Tiesioginė buvimo vieta + Bendrinti vietą + Norėdami bendrinti tiesioginę buvimo vietą šiame kambaryje, turite turėti tinkamus leidimus. + Neturite leidimo bendrinti tiesioginę buvimo vietą + Atnaujinta prieš %1$s + Laikinas pritaikymas: vietos išlieka kambario istorijoje + Įjungti tiesioginį buvimo vietos bendrinimą + Bendrinama buvimo vieta + ${app_name} tiesioginė buvimo vieta + %1$s liko + Sustabdyti + Tiesiogiai iki %1$s + Žiūrėti tiesioginę buvimo vietą + Tiesioginė buvimo vieta baigėsi + Įkeliama tiesioginė vieta… + Tiesioginė buvimo vieta įjungta + Nepavyksta įkelti žemėlapio +\nŠis namų serveris gali būti nesukonfigūruotas rodyti žemėlapius. + Nepavyko įkelti žemėlapio + Atidaryti per + ${app_name} negalėjo pasiekti jūsų vietos. Prašome pabandyti vėliau. + ${app_name} negalėjo pasiekti jūsų vietos + 8 valandas + 1 valandą + 15 minučių + Bendrinti savo tiesioginę buvimo vietą + Bendrinti šią vietą + Bendrinti šią vietą + Bendrinti tiesioginę buvimo vietą + Bendrinti tiesioginę buvimo vietą + Bendrinti mano dabartinę vietą + Bendrinti mano dabartinę vietą + Priartinti esamą vietą + Pasirinktos vietos smeigtukas žemėlapyje + Žemėlapis + Rezultatai atskleidžiami tik tada, kai baigiate apklausą + Uždaryta apklausa + Balsuotojai mato rezultatus iškart po balsavimo + Atidaryti apklausą + Apklausos tipas + Redaguoti apklausą + Ar tikrai norite pašalinti šią apklausą\? Pašalinę ją negalėsite susigrąžinti. + Tai neleis žmonėms balsuoti ir bus rodomi galutiniai apklausos rezultatai. + Pašalinti apklausą + Apklausa baigėsi + Prabalsuota + Baigti apklausą + laimėtojo parinktis + Rezultatai bus matomi pasibaigus apklausai + Nėra balsų + Iš naujo paleiskite programą, kad pakeitimas įsigaliotų. + Įjungti LaTeX matematika + %s nustatymuose, kad gautumėte kvietimus tiesiogiai į ${app_name}. + Kvietimas į šią erdvę buvo išsiųstas į %s, kuris nėra susijęs su jūsų paskyra + Kvietimas į šį kambarį buvo išsiųstas į %s, kuris nėra susijęs su jūsų paskyra + Atkreipkite dėmesį, kad atnaujinus bus sukurta nauja kambario versija. Visos dabartinės žinutės liks šiame archyvuotame kambaryje. + Kiekvienas iš %s galės rasti šį kambarį ir prisijungti prie jo - nereikės visų kviesti rankiniu būdu. Tai galėsite bet kada pakeisti kambario nustatymuose. + (%1$s) + %1$s (%2$s) + Nepavyko paleisti %1$s + Pristabdyti %1$s + Paleisti %1$s + %1$d minutės %2$d sekundės + %1$s, %2$s, %3$s + %1$ds liko + Atsiprašome, bandant prisijungti įvyko klaida: %s + Atnaujinti į rekomenduojamą kambario versiją + Šiame kambaryje naudojama kambario versija %s, kurią šis namų serveris pažymėjo kaip nestabilią. + Norint atnaujinti kambarį, reikia leidimo + Jūs atnaujinsite šį kambarį iš %1$s į %2$s. + Kambario atnaujinimas yra išplėstinis veiksmas ir paprastai rekomenduojamas, kai kambarys yra nestabilus dėl klaidų, trūkstamų funkcijų ar saugumo spragų. +\nPaprastai tai turi įtakos tik tam, kaip kambarys apdorojamas serveryje. + Atnaujinti privatų kambarį + Atnaujinti viešą kambarį + Kai kurie kambariai gali būti paslėpti, nes yra privatūs ir į juos reikia pakvietimo. + Kai kurie kambariai gali būti paslėpti, nes yra privatūs ir į juos reikia pakvietimo. +\nJūs neturite leidimo pridėti kambarių. + Šioje erdvėje nėra kambarių + Dėl papildomos informacijos kreipkitės į savo namų serverio administratorių + Atrodo, kad jūsų namų serveris dar nepalaiko erdvių + Norite eksperimentuoti\? +\nĮ erdvę galite įtraukti esamas erdves. + Visi kambariai kuriuose esate, bus rodomi pradžioje. + Valdyti kambarius ir erdves + Pažymėti kaip nesiūlomą + Pažymėti kaip siūlomą + Siūlomas + Valdyti kambarius + Ieškote ko nors ne iš %s\? + %s kviečia tave + Rodyti naujausią profilio informaciją (avatarą ir rodomą vardą) visose žinutėse. + Rodyti naujausią naudotojo informaciją + Pastaba: programa bus paleista iš naujo + Įjungti temų žinutes + Jūsų sistema automatiškai išsiųs žurnalus, kai įvyks negalėjimo iššifruoti klaida + Automatiškai pranešti apie iššifravimo klaidas. + Erdvės - tai naujas kambarių ir žmonių grupavimo būdas. + Įtraukite erdvę į bet kurią valdomą erdvę. + Pridėti esamas erdves + Pridėti esamus kambarius + Pridėti esamus kambarius ir erdvę + Kai kurie rezultatai gali būti paslėpti, nes jie yra privatūs ir į juos reikia pakvietimo. + Rezultatų nerasta + Iš temos + Patarimas: Ilgai bakstelėkite žinutę ir naudokite “%s”. + Temos padeda išlaikyti pokalbių temą ir lengviau juos sekti. + Išlaikykite diskusijas organizuotas su temomis + Rodo visas temas, kuriose dalyvavote + Mano temos + Rodo visas temas iš dabartinio kambario + Visos temos + Filtras + Visos temos + Tema + Keisti leidimus + Keisti pagrindinį kambario adresą + Keisti kambario avatarą + Keisti valdiklius + Pranešti visiems + Pašalinti kitų išsiųstas žinutes + Užblokuoti naudotojus + Pašalinti naudotojus + Keisti nustatymus + Kviesti naudotojus + Siųsti žinutes + Įjungti kambario šifravimą + Keisti kambario pavadinimą + Keisti istorijos matomumą + %s atnaujino čia. diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index f1fa1502c1..1787653fae 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -469,7 +469,7 @@ Tēma Atšifrēšanas kļūda Ierīces nosaukums - Sesijas ID + Sesijas ID Sesijas atslēga Eksportēt istabas šifrēšanas atslēgas Eksportēt istabas atslēgas diff --git a/library/ui-strings/src/main/res/values-nb-rNO/strings.xml b/library/ui-strings/src/main/res/values-nb-rNO/strings.xml index 031b380c7e..7af718d920 100644 --- a/library/ui-strings/src/main/res/values-nb-rNO/strings.xml +++ b/library/ui-strings/src/main/res/values-nb-rNO/strings.xml @@ -119,7 +119,7 @@ Bannlyste brukere Avansert Tema - Økt-ID + Økt-ID Øktnøkkel Eksporter Importer diff --git a/library/ui-strings/src/main/res/values-nl/strings.xml b/library/ui-strings/src/main/res/values-nl/strings.xml index b1d239963e..ce122b0646 100644 --- a/library/ui-strings/src/main/res/values-nl/strings.xml +++ b/library/ui-strings/src/main/res/values-nl/strings.xml @@ -3,10 +3,10 @@ Uitnodiging van %s %1$s heeft %2$s uitgenodigd %1$s heeft u uitgenodigd - %1$s neemt nu deel aan het gesprek - %1$s heeft het gesprek verlaten + %1$s is deelnemer geworden van de kamer + %1$s heeft het de kamer verlaten %1$s heeft de uitnodiging geweigerd - %1$s heeft %2$s uit het gesprek verwijderd + %1$s heeft %2$s verwijderd %1$s heeft %2$s ontbannen %1$s heeft %2$s verbannen %1$s heeft de uitnodiging van %2$s ingetrokken @@ -15,20 +15,20 @@ %1$s heeft zijn/haar naam aangepast van %2$s naar %3$s %1$s heeft zijn/haar naam verwijderd (%2$s) %1$s heeft het onderwerp veranderd naar: %2$s - %1$s heeft de gespreksnaam veranderd naar: %2$s + %1$s heeft de kamernaam veranderd naar: %2$s %s heeft een video-oproep gemaakt. %s heeft een spraakoproep gemaakt. %s heeft de oproep beantwoord. %s heeft de oproep beëindigd. - %1$s heeft de toekomstige gespreksgeschiedenis zichtbaar gemaakt voor %2$s - alle deelnemers aan het gesprek, vanaf het punt dat ze zijn uitgenodigd. - alle deelnemers aan het gesprek, vanaf het punt dat ze zijn toegetreden. - alle deelnemers aan het gesprek. + %1$s heeft de toekomstige kamergeschiedenis zichtbaar gemaakt voor %2$s + alle kamerdeelnemers, vanaf het punt dat ze zijn uitgenodigd. + alle kamerdeelnemers, vanaf het punt dat ze deelnemer zijn geworden. + alle kamerdeelnemers. iedereen. (avatar is ook veranderd) - %1$s heeft de gespreksnaam verwijderd - %1$s heeft het gespreksonderwerp verwijderd - %1$s heeft een uitnodiging naar %2$s gestuurd om het gesprek toe te treden + %1$s heeft de kamernaam verwijderd + %1$s heeft het kameronderwerp verwijderd + %1$s heeft een uitnodiging naar %2$s gestuurd om deelnemer te worden van de kamer %1$s heeft de uitnodiging voor %2$s aanvaard ** Kan niet ontsleutelen: %s ** Het apparaat van de afzender heeft geen sleutels voor dit bericht gestuurd. @@ -36,27 +36,27 @@ Matrix-fout E-mailadres Telefoonnummer - Gespreksuitnodiging + Kameruitnodiging %1$s en %2$s - Leeg gesprek + Lege kamer Initiële synchronisatie: \nAccount wordt geïmporteerd… Initiële synchronisatie: \nCrypto wordt geïmporteerd Initiële synchronisatie: -\nGesprekken worden geïmporteerd +\nKamers importeren Initiële synchronisatie: -\nDeelgenomen gesprekken worden geïmporteerd -\nDit kan enige tijd in beslag nemen +\nGesprekken worden geladen +\nAls u aan veel kamers deelneemt kan dit even duren Initiële synchronisatie: -\nUitgenodigde gesprekken worden geïmporteerd +\nUitgenodigde kamers worden geïmporteerd Initiële synchronisatie: -\nVerlaten gesprekken worden geïmporteerd +\nVerlaten kamers worden geïmporteerd Initiële synchronisatie: \nAccountgegevens worden geïmporteerd - %s heeft dit gesprek geüpgraded. + %s heeft deze kamer geüpgraded. Bericht wordt verstuurd… - %1$s heeft de uitnodiging voor %2$s om het gesprek toe te treden ingetrokken + %1$s heeft de uitnodiging voor %2$s om deelnemer te worden van de kamer ingetrokken Uitnodiging van %1$s. Reden: %2$s %1$s heeft %2$s uitgenodigd. Reden: %3$s %1$s heeft u uitgenodigd. Reden: %2$s @@ -69,8 +69,8 @@ %1$s heeft de uitnodiging voor %2$s aanvaard. Reden: %3$s %1$s heeft de uitnodiging van %2$s ingetrokken. Reden: %3$s - %1$s heeft %2$s als gespreksadres toegevoegd. - %1$s heeft %2$s als gespreksadressen toegevoegd. + %1$s heeft %2$s als kameradres toegevoegd. + %1$s heeft %2$s als kameradressen toegevoegd. %1$s heeft %2$s als gespreksadres verwijderd. @@ -123,7 +123,7 @@ Logboek versturen Crash-logboek versturen Schermafdruk versturen - Fout melden + Probleem melden Beschrijf de fout. Wat heeft u gedaan\? Wat verwachtte u dat er zou gebeuren\? Wat is er echt gebeurd\? Beschrijf hier uw probleem Om het probleem te kunnen onderzoeken worden logboeken van deze cliënt met de foutmelding verstuurd. Deze foutmelding, inclusief de logboeken en schermafdruk, zullen niet openbaar zichtbaar zijn. Indien u liever alleen de bovenstaande tekst verstuurt, haal dan het vinkje weg: @@ -132,7 +132,7 @@ Versturen van foutmelding is mislukt (%s) Voortgang (%s%%) De toepassing is de vorige keer gecrasht. Wilt u dit melden\? - Gesprek toetreden + Deelnemen aan kamer Inlognaam Afmelden Server-URL @@ -172,9 +172,9 @@ NEE Verdergaan Verwijderen - Toetreden + Deelnemen Afwijzen - Ga naar ongelezen + Naar ongelezen springen Gesprek verlaten Weet u zeker dat u het gesprek wilt verlaten\? TWEEGESPREKKEN @@ -210,7 +210,7 @@ Telefoonnummer toevoegen Toon informatie over de app in de systeeminstellingen. App-informatie - Meldingen voor deze account inschakelen + Meldingen voor dit account inschakelen Meldingen voor deze sessie inschakelen Berichten in één-op-één-gesprekken Berichten in groepsgesprekken @@ -227,7 +227,7 @@ Copyright Privacybeleid Cache wissen - Persoonsinstellingen + Gebruikersinstellingen Meldingen Genegeerde personen Overige @@ -265,7 +265,7 @@ Iedereen Alleen deelnemers (vanaf het moment dat deze optie wordt geselecteerd) Alleen deelnemers (vanaf het moment dat ze worden uitgenodigd) - Alleen deelnemers (vanaf het moment dat ze toetreden) + Alleen deelnemers (vanaf het moment dat ze deelnemer zijn geworden) Verbannen personen Geavanceerd Interne ID van dit gesprek @@ -275,7 +275,7 @@ Niet instellen als hoofdadres Ontsleutelingsfout Publieke naam - Sessie ID + Sessie-ID Sessiesleutel E2E-gesprekssleutels exporteren Gesprekssleutels exporteren @@ -294,7 +294,7 @@ Verifiëren Om te verifiëren dat deze sessie vertrouwd kan worden, contacteert u de eigenaar via een andere methode (bv. persoonlijk of via een telefoontje) en vraagt u hem/haar of de sleutel die hij/zij ziet in zijn/haar persoonsinstellingen van deze sessie overeenkomt met de sleutel hieronder: Als het overeenkomt, drukt u op de knop ‘Verifiëren’ hieronder. Als het niet overeenkomt, dan onderschept iemand anders deze sessie en zou u het beter blokkeren. In de toekomst zal dit verificatieproces verbeterd worden. - Kies een gesprekscatalogus + Kamermap kiezen Servernaam Alle gesprekken op server %s Alle lokale gesprekken op %s @@ -334,7 +334,7 @@ user_id ontbreekt in het verzoek. Gesprek %s is niet zichtbaar. Matrix-apps toevoegen - Geluidsmeldingen + Belangrijke meldingen Stille meldingen Foutmelding Foto maken @@ -423,7 +423,7 @@ Voer uw wachtwoord in. Beschrijf het probleem in het Engels, indien mogelijk. Media bekijken vóór het versturen - Toont een actie + Geeft activiteit weer Verbant persoon met gegeven ID Heft verbanning van persoon met gegeven ID op Stel het machtsniveau van een persoon in @@ -456,7 +456,7 @@ Aanvaarden Gelieve het beleid van deze server te lezen en aanvaarden: Oproepen - Gebruik de standaardbeltoon van ${app_name} voor inkomende oproepen + Standaardbeltoon van ${app_name} gebruiken voor inkomende oproepen Beltoon voor inkomende oproepen Selecteer beltoon voor oproepen: Eruit sturen @@ -551,7 +551,7 @@ ${app_name} wordt niet beperkt door accuoptimalisatie. Als een persoon een apparaat los van de oplader een tijd laat stilliggen, met het scherm uitgeschakeld, gaat het apparaat in slaapmodus. Dit verhindert apps de toegang tot het netwerk, en stelt hun taken, synchronisaties en standaardalarmen uit. Optimalisatie negeren - Lawaaiierige meldingen configureren + Belangrijke meldingen configureren Oproepmeldingen configureren Stille meldingen configureren Bepaal de LED-kleur, vibratie, geluid, … @@ -722,7 +722,7 @@ Gebruik een integratiebeheerder om bots, bruggen, widgets en stickerpakketten te beheren. \nIntegratiebeheerders ontvangen configuratiedata en kunnen widgets aanpassen, gespreksuitnodigingen versturen en bestuursniveaus instellen namens u. Ontdekken - Beheer uw ontdekinstellingen. + Beheer uw ontdekkingsinstellingen. Integraties toestaan Integratiebeheerder Widget @@ -774,18 +774,18 @@ Gebeurtenis verwijderd door persoon Gebeurtenis gemodereerd door gesprek beheerder Niet correcte gebeurtenis, kan niet weergeven - Maak een nieuw gesprek aan + Nieuwe kamer aanmaken Geen netwerk. Controleer uw internet verbinding. Wijzigen - Wijzig netwerk + Netwerk wijzigen Even wachten… - Dit gesprek kan niet worden voorvertoond + Deze kamer kan niet worden voorvertoond Gesprekken Directe Berichten AANMAKEN - Gespreksnaam + Naam Publiek - Iedereen kan deze kamer kunnen toetreden + Iedereen kan deelnemer worden van deze kamer Afspelen U heeft het hoofdadres voor dit gesprek verwijderd. U heeft %1$s uitgenodigd. Reden: %2$s @@ -861,8 +861,8 @@ U heeft een audiogesprek geopend. U heeft een videogesprek geopend. U heeft de kamernaam veranderd naar: %1$s - U heeft de kamer afbeelding aangepast - %1$s heeft de kamer afbeelding aangepast + U heeft de kamerafbeelding aangepast + %1$s heeft de kamerafbeelding aangepast U heeft het onderwerp gewijzigd naar: %1$s U heeft uw weergavenaam verwijderd (voorheen %1$s) U heeft de uitnodiging van %1$s ingetrokken @@ -891,8 +891,8 @@ U heeft %1$s als gespreksadressen verwijderd. - U heeft %1$s als gespreksadres toegevoegd. - U heeft %1$s als gespreksadressen toegevoegd. + U heeft %1$s als kameradres toegevoegd. + U heeft %1$s als kameradressen toegevoegd. U heeft de uitnodiging van %1$s ingetrokken. Reden: %2$s U heeft de uitnodiging voor %1$s aanvaard. Reden: %2$s @@ -913,12 +913,12 @@ • Servers die overeenkomen met %s zijn verbannen. U heeft hier geüpgraded. %s heeft hier geüpgraded. - U heeft toekomstige gespreksgeschiedenis zichtbaar gemaakt voor %1$s + U heeft toekomstige kamergeschiedenis zichtbaar gemaakt voor %1$s %1$ds over %s is toegetreden. Conclusie Bevestiging Kamerinstellingen - Gespreksnaam + Kamernaam Integraties Beheren %d uitnodiging @@ -940,7 +940,7 @@ PIN Bevestigen Uitnodiging intrekken Contactpersonen - Gespreksnaam + Kamernaam Beveiligingszin Instellen Beveiligde backup @@ -962,7 +962,7 @@ Sleutelverzoeken Verwijderen Bevestigen Accountgegevens - Ontwikkel Gereedschap + Ontwikkelaarsgereedschap QR-code Sleutels herstellen Gekruist Ondertekenen Initialiseren @@ -971,7 +971,7 @@ Actieve Sessies Versleuteling inschakelen Versleuteling inschakelen\? - Berichtverwerker + Berichtbewerker Gesprek Verlaten Eén persoon @@ -1043,7 +1043,7 @@ Directe Berichten Feedback Token registreren - Pushregels + Push-regels Bericht verwijderd Beveiligde Backup Actieve widgets @@ -1061,7 +1061,7 @@ SSL-fout. Camera wisselen Draadloze Koptelefoon - Spaces + Ruimten Wisselen Opwaarderen Aanbevolen @@ -1187,7 +1187,7 @@ Kopiëren Geef toestemming om de camera te gebruiken via de systeeminstellingen om deze actie uit te voeren. Sommige rechten ontbreken om deze actie uit te voeren, geeft a.u.b. toestemming via de systeeminstellingen. - Spaces + Ruimten Begin met chatten Herstellen Afwijzen @@ -1224,13 +1224,13 @@ Aan de slag Spacerechten Gespreksrechten - Door deze persoon niet meer de verbannen kan hij/zij opnieuw toetreden tot de space. - Door deze persoon niet meer de verbannen kan hij/zij opnieuw toetreden tot het gesprek. + Door de verbanning op te heffen kan deze gebruiker opnieuw deelnemer worden van de ruimte. + Door de verbanning op te heffen kan deze gebruiker opnieuw deelnemer worden van de kamer. Door deze persoon te verbannen zal hij/zij verwijderd worden uit deze space en voorkomen dat hij/zij opnieuw toetreedt. Reden voor verbanning - Door deze persoon de verwijderen zal hij/zij niet meer in deze space zitten. + De gebruiker zal worden verwijderd uit deze ruimte. \n -\nOm te voorkomen dat hij/zij opnieuw toetreedt, kunt u hem/haar ook verbannen. +\nOm te voorkomen dat ze opnieuw toetreden, kunt u ze verbannen. Door deze persoon te verwijderen zal hij/zij niet meer in dit gesprek zitten. \n \nOm te voorkomen dat hij/zij opnieuw toetreedt, kun je hem/haar ook verbannen. @@ -1241,7 +1241,7 @@ \n \nU kunt deze actie op elk moment ongedaan maken in de algemene instellingen. U kunt deze wijziging niet ongedaan maken omdat uzelf degradeert, als u de laatste persoon met rechten bent in het gesprek zal het onmogelijk zijn om opnieuw rechten te krijgen. - Dit gesprek is niet publiek. U kunt niet opnieuw toetreden zonder uitnodiging. + Deze kamer is niet publiek. U kunt niet opnieuw deelnemer worden zonder uitnodiging. Toegang verlenen tot uw contactpersonen. Om de QR-code te scannen moet u toegang verlenen tot de camera. Oproep beëindigen… @@ -1353,7 +1353,7 @@ Toevoegen aan lage prioriteit Verwijder van favorieten Toevoegen aan favorieten - Alle berichten (luidruchtig) + Alle belangrijke berichten Deze inhoud is als ongepast gerapporteerd. \n \nAls u geen inhoud van deze persoon meer wilt zien, kunt u deze negeren om hun berichten te verbergen. @@ -1396,7 +1396,7 @@ Het lijkt erop dat de server er te lang over doet om te reageren. Dit kan worden veroorzaakt door een slechte verbinding of een fout met de server. Probeer het over een tijdje opnieuw. Probeer het opnieuw zodra u de algemene voorwaarden van uw homeserver hebt geaccepteerd. Uitgebreide logboeken helpen ontwikkelaars door meer logboeken te verstrekken wanneer u een RageShake verzendt. Zelfs wanneer ingeschakeld, registreert de toepassing geen berichtinhoud of andere privégegevens. - Uitgebreide logboeken inschakelen. + Uitgebreide logboeken inschakelen Ga akkoord met de servicevoorwaarden van de identiteitsserver (%s), zodat u vindbaar bent op e-mailadres of telefoonnummer. U deelt momenteel e-mailadressen of telefoonnummers op de identiteitsserver %1$s. U moet opnieuw verbinding maken met %2$s om ze niet meer te delen. De verificatiecode is niet correct. @@ -1411,7 +1411,7 @@ Stuur e-mailadressen en telefoonnummers naar %s Toestemming geven Mijn toestemming intrekken - Uw server-beleid + Uw thuisserverbeleid Kan geen server bereiken op de URL %s. Controleer uw link of kies handmatig een server. Uw contacten zijn privé. Om personen van uw contacten te ontdekken, hebben we uw toestemming nodig om contactgegevens naar uw identiteitsserver te sturen. We hebben u een bevestigingsmail gestuurd naar %s, controleer eerst uw e-mail en klik op de bevestigingslink @@ -1467,8 +1467,8 @@ Afbeelding comprimeren… Bestand versturen (%1$s / %2$s) Miniatuur versturen (%1$s / %2$s) - Toon volledige geschiedenis in versleutelde kamers - Toon verborgen gebeurtenissen op de tijdlijn + Volledige geschiedenis in versleutelde kamers weergeven + Verborgen gebeurtenissen op de tijdlijn weergeven Geef feedback De feedback kan niet worden verzonden (%s) Bedankt, uw feedback is succesvol verzonden @@ -1479,8 +1479,8 @@ Bedankt, de suggestie is succesvol verzonden Beschrijf hier uw suggestie Schrijf hieronder uw suggestie. - Doe een suggestie - Systeem instellingen + Een voorstel doen + Systeeminstellingen Versies Hulp bij het gebruik van ${app_name} Hulp en ondersteuning @@ -1500,9 +1500,9 @@ \n \n%s Kameronderwerp (optioneel) - Aanmaken nieuwe Space - Toon een aanduiding voor verwijderde berichten - Toon verwijderde berichten + Nieuwe ruimte aanmaken + Geeft een plaatsvervangende melding weer voor verwijderde berichten. + Verwijderde berichten weergeven Beveiligde back-up instellen Beveiliging tegen verlies van toegang tot versleutelde berichten en gegevens De herstelsleutel is opgeslagen. @@ -1565,7 +1565,7 @@ Gepubliceerde adressen kunnen door iedereen op elke server worden gebruikt om lid te worden van uw kamer. Om een adres te publiceren, moet het eerst als lokaal adres worden ingesteld. Gepubliceerde adressen Adressen van deze kamer bekijken en beheren. - Spaceadressen + Ruimte-adressen Bekijk en beheer de adressen van deze kamer en de zichtbaarheid ervan in de kamerdirectory. Kameradressen Sta toe om gasten te laten deelnemen @@ -1584,7 +1584,7 @@ Deze server biedt geen beleid. Bibliotheken van derden Uw identiteitsserverbeleid - ${app_name} beleid + ${app_name}-beleid We delen geen informatie met derden We registreren of profileren geen accountgegevens hier @@ -1601,7 +1601,7 @@ Voeg een knop toe aan de invoerveld om het emoji-toetsenbord te openen Emoji-toetsenbord weergeven Gebruik /confetti commando of stuur een bericht met ❄️ of 🎉 - Toon chateffecten + Chateffecten weergeven Kamer upgrades Berichten door bot Kameruitnodigingen @@ -1754,7 +1754,7 @@ Pincode is vereist na 2 minuten ${app_name} niet te hebben gebruikt. Pincode vereist na 2 minuten Geef alleen het aantal ongelezen berichten weer in een eenvoudige melding. - Toon details zoals kamernamen en berichtinhoud. + Geeft details weer zoals kamernamen en berichtinhoud. Inhoud in meldingen weergeven Pincode is de enige manier om ${app_name} te ontgrendelen. Schakel apparaatspecifieke biometrische gegevens in, zoals vingerafdrukken en gezichtsherkenning. @@ -1831,8 +1831,8 @@ Andere beschikbare talen Deel deze code met mensen zodat ze deze kunnen scannen om u toe te voegen en te beginnen met chatten. Mijn code - Deel mijn code - Scan een QR-code + Mijn code delen + Een QR-code scannen We kunnen geen personen uitnodigen. Controleer de personen die u wilt uitnodigen en probeer het opnieuw. Uitnodigingen verzonden naar %1$s en nog één @@ -1843,7 +1843,7 @@ Uitnodiging verzonden naar %1$s 🔐️ Doe mee met ${app_name} Hé, praat met me op ${app_name}: %s - Nodig vrienden uit + Vrienden uitnodigen Mensen toevoegen We kunnen je DM niet maken. Controleer de personen die u wilt uitnodigen en probeer het opnieuw. De link %1$s brengt u naar een andere site: %2$s. @@ -1912,7 +1912,7 @@ Kan sleutels niet importeren Wachten op %s… Bijna daar! Op bevestiging wachten… - Bijna daar! Toont het andere apparaat een vinkje\? + Bijna klaar! Toont het andere apparaat een vinkje\? Een onderwerp toevoegen %s om mensen te laten weten waar deze kamer over gaat. Dit is het begin van uw privéberichtgeschiedenis met %s. @@ -1989,7 +1989,7 @@ \nWees voorzichtig, het kan leiden tot onverwacht gedrag. Vliegtuigmodus is ingeschakeld Verbinding met de server is verbroken - Bijna daar! Toont %s een vinkje\? + Bijna klaar! Toont %s een vinkje\? Totdat deze persoon deze sessie vertrouwt, worden berichten die van en naar de sessie worden verzonden, gelabeld met waarschuwingen. U kunt het ook handmatig verifiëren. %1$s (%2$s) aangemeld met een nieuwe sessie: Deze sessie wordt vertrouwd voor veilig berichtenverkeer omdat %1$s (%2$s) deze heeft geverifieerd: @@ -2011,7 +2011,7 @@ Serverversie Server naam Afmelden voor deze sessie - Toon alle sessies + Alle sessies tonen Uw serverbeheerder heeft standaard end-to-end versleuteling uitgeschakeld in privékamers en privéberichten. Kruisondertekenen is niet ingeschakeld Kruisondertekenen is ingeschakeld. @@ -2070,21 +2070,21 @@ Ze komen niet overeen Niet-vertrouwd inloggen Uw e-maildomein is niet geautoriseerd om op deze server te registreren - Space aanmaken… + Ruimte aanmaken… Kamer aanmaken… Sommige tekens zijn niet toegestaan Geef een kameradres op Dit adres is al in gebruik - Space adres + Ruimte-adres U kunt dit inschakelen als de kamer alleen wordt gebruikt voor samenwerking met interne teams op uw server. Dit kan later niet meer worden gewijzigd. Blokkeer iedereen die geen deel uitmaakt van %s om ooit deel te nemen aan deze kamer Verberg geavanceerd - Toon geavanceerd + Geavanceerd weergeven Eenmaal ingeschakeld, kan versleuteling niet worden uitgeschakeld. Voegt ( ͡° ͜ʖ ͡°) toe aan een bericht in platte tekst Voegt ¯\\_(ツ)_/¯ toe aan een bericht in platte tekst - Toon wat nuttige informatie om te helpen bij het debuggen van de applicatie - Toon debug-informatie op het scherm + Geeft wat nuttige informatie weer om te helpen bij foutopsporing van de app. + Foutopsporingsinformatie op het scherm weergeven ${app_name} kan vaker crashen als er een onverwachte fout optreedt Laat alleen de eerste resultaten zien, typ meer letters… Schud je telefoon om de detectiedrempel te testen @@ -2157,9 +2157,9 @@ Ik heb mijn e-mailadres geverifieerd Tik op de link om uw nieuwe wachtwoord te bevestigen. Klik hieronder als u de link hebt gevolgd die erin staat. Word eigenaar van uw gesprekken. - Space aanmaken - Space aanmaken… - Aanmaken een space + Ruimte aanmaken + Ruimte aanmaken… + Een ruimte aanmaken Gebeurtenis inhoud Houd er rekening mee dat bij het upgraden een nieuwe versie van de kamer wordt gemaakt. Alle huidige berichten blijven in deze gearchiveerde kamer. Iedereen in een ouderkamer kan deze kamer vinden en er lid van worden. Het is niet nodig om iedereen handmatig uit te nodigen. U kunt dit op elk moment wijzigen in de kamer instellingen. @@ -2247,7 +2247,7 @@ Experimenteel voelen\? \nU kunt bestaande spaces aan een space toevoegen. Alle kamers waarin u deelneemt, worden weergegeven in Home. - Toon alle kamers in Home + Alle kamers op startscherm weergeven Kamers en spaces beheren Markeren als aanbevolen Markeren als niet aanbevolen @@ -2300,16 +2300,16 @@ Voeg wat details toe om het te laten opvallen. U kunt deze op elk moment wijzigen. Alleen op uitnodiging, het beste voor uzelf of teams Open voor iedereen, het beste voor gemeenschappen - Een privé space voor u en uw teamgenoten + Een privé-ruimte voor u en uw teamgenoten Ik en teamgenoten Een privé space om je kamers te organiseren Alleen ik Zorg ervoor dat de juiste mensen toegang hebben tot %s. Met wie werkt u samen\? U kunt dit later wijzigen - Wat voor soort space wilt u aanmaken\? - Uw privé space - Uw openbare space + Wat voor soort ruimte wilt u aanmaken\? + Uw privé-ruimte + Uw openbare ruimte Space toevoegen Privé space Openbare space @@ -2352,7 +2352,7 @@ Locatie De versleuteling is verkeerd geconfigureerd, zodat u geen berichten kunt versturen. Klik om instellingen te openen. De versleuteling is verkeerd geconfigureerd, zodat u geen berichten kunt versturen. Neem contact op met een beheerder om de versleuteling in een geldige staat te herstellen. - Toon bericht bubbels + Berichtbubbels weergeven Kan kaart niet laden Kaart Let op: app wordt opnieuw gestart @@ -2393,7 +2393,7 @@ %1$d meer %1$d meer - Toon minder + Minder weergeven Locatie delen is bezig ${app_name} Live locatie Stop @@ -2471,8 +2471,8 @@ \n \nHoud er rekening mee dat deze actie de app opnieuw zal starten en dat dit enige tijd kan duren. Initieel synchronisatieverzoek - Toon de laatste profielinformatie (avatar en weergavenaam) voor alle berichten. - Toon laatste persoonsinformatie + Geeft de meest recente gebruikersinfo (avatar en weergavenaam) weer voor alle berichten. + Meest recente gebruikersinfo weergeven Bezet Back-up heeft een geldige handtekening van deze persoon. %1$s geleden bijgewerkt @@ -2563,7 +2563,7 @@ %s moet uw account verifiëren Vul uw e-mailadres in Lees de voorwaarden en het beleid van %s door - Serverbeleid + Serverbeleiden Neem contact op Element Matrix Services (EMS) is een robuuste en betrouwbare hostingservice voor snelle, veilige en realtime communicatie. Ontdek hoe op element.io/ems Wilt u uw eigen server hosten\? @@ -2596,15 +2596,15 @@ %1$s en %2$s E-mailadres niet geverifieerd, controleer je inbox - Toon alle sessies (V2, WIP) + Alle sessies weergeven (V2, WIP) Kan kaart niet laden \nDeze server is mogelijk niet geconfigureerd om kaarten weer te geven. Open instellingen - Voor de beste beveiliging verifieert u uw sessies en meldt u zich af bij elke sessie die u niet meer herkent of gebruikt. - Andere sessies + Voor de beste beveiliging verifieert u uw sessies en meldt u zich af bij elke sessie die u niet meer herkent of gebruikt. + Andere sessies Sessies Lijst met publieke spaces - Maak een nieuw gesprek of een nieuwe kamer + Nieuw gesprek of nieuwe kamer aanmaken Personen Favorieten Ongelezen @@ -2613,10 +2613,59 @@ Activiteit Sorteer op Recente tonen - Toon filters + Filters weergeven Lay-outvoorkeuren Ontdek kamers Kamer creëren - Start gesprek + Gesprek starten Alle gesprekken + U kunt feedback geven via het menu rechtsboven. + Krijg sneller en gemakkelijker toegang tot uw ruimten (rechtsonder). + Om ${app_name} te versimpelen zijn tabbladen nu optioneel. U kunt ze beheren in het menu rechtsboven. + Hier zullen uw ongelezen berichten verschijnen wanneer u deze heeft. + De allesomvattende beveiligde chat-app voor teams, vrienden en organisaties. Maak een gesprek aan of word deelnemer van een bestaande kamer om te beginnen. + Ruimten zijn een nieuwe manier om kamers en personen te groeperen. Voeg een bestaande kamer toe, of maak een nieuwe aan via de knop rechtsonder. + + Overweeg uit te loggen van oude sessies (%1$d of meer dagen) welke u niet meer gebruikt. + Overweeg uit te loggen van oude sessies (%1$d of meer dagen) welke u niet meer gebruikt. + + Verifieer of log uit van ongeverifieerde sessies. + Verbeter uw accountbeveiliging door deze aanbevelingen te volgen. + + Al %1$d+ dag inactief (%2$s) + Al %1$d+ dagen inactief (%2$s) + + Beveiligingsaanbevelingen + Niet-geverifieerde sessies + Inactieve sessies + %s +\nziet er vrij leeg uit. + Welkom bij ${app_name}, +\n%s. + Niets te melden. + Welkom bij een nieuw uiterlijk! + Toegang tot ruimten + Feedback geven + Uitproberen + Niet-geverifieerd · Laatste activiteit %1$s + Geverifieerd · Laatste activiteit %1$s + Alle bekijken (%1$d) + Details bekijken + Sessie verifiëren + Sorry, deze kamer kon niet worden gevonden. +\nProbeer het later opnieuw. %s + Dit is waar uw nieuwe verzoeken en uitnodigingen zullen verschijnen. + Ruimten zijn een nieuwe manier om kamers en personen te groeperen. Maak een ruimte aan om te beginnen. + Ongeverifieerde sessie + Geverifieerde sessie + Onbekend apparaattype + Desktop + Web + Mobiel + Niets nieuws. + Uitnodigingen + Nog geen ruimten. + %s subitems inklappen + %s subitems uitvouwen + Ruimte aanpassen diff --git a/library/ui-strings/src/main/res/values-nn/strings.xml b/library/ui-strings/src/main/res/values-nn/strings.xml index a56ba0ac30..45c8679736 100644 --- a/library/ui-strings/src/main/res/values-nn/strings.xml +++ b/library/ui-strings/src/main/res/values-nn/strings.xml @@ -310,7 +310,7 @@ Preg Noko gjekk gale med dekrypteringa Offentleg namn - Økt-ID + Økt-ID Sesjonsnøkkel Eksporter E2E-romnøkklar Eksporter romnøkklar diff --git a/library/ui-strings/src/main/res/values-pl/strings.xml b/library/ui-strings/src/main/res/values-pl/strings.xml index 682fd1df1e..b7b73eb9e6 100644 --- a/library/ui-strings/src/main/res/values-pl/strings.xml +++ b/library/ui-strings/src/main/res/values-pl/strings.xml @@ -145,7 +145,7 @@ Przejdź do pierwszej nieprzeczytanej wiadomości Opuść pokój Czy na pewno chcesz opuścić pokój? - WIADOMOŚCI BEZPOŚREDNIE + Wiadomości bezpośrednie Zaproś Blokuj Odbanuj @@ -231,7 +231,7 @@ Ustaw jako główny adres Motyw Nazwa publiczna - ID sesji + ID sesji Eksportuj Wprowadź hasło Potwierdź hasło @@ -548,7 +548,7 @@ Pokoje Dodaj reakcję Utwórz nowy pokój - Wiadomości Bezpośrednie + Wiadomości bezpośrednie STWÓRZ Nazwa Publiczny @@ -654,7 +654,7 @@ Proszę wykonać kopię Preferencje Głos i wideo - Wiadomości Bezpośrednie + Wiadomości bezpośrednie Filtruj rozmowy… Wyślij nową wiadomość bezpośrednią Wersja Matrix SDK @@ -735,7 +735,7 @@ Ustal jak inni mogą odnaleść twoje konto. Media Domyślne źródło mediów - Odzyskiwanie zaszyforwanych wiadomości + Odzyskiwanie zaszyfrowanych wiadomości %1$s: %2$d wiadomość %1$s: %2$d wiadomości @@ -841,7 +841,7 @@ Url: Format: Zarejestruj token - Dziękujemy, sugestia została szczęśliwie wysłana + Dziękujemy, sugestia została pomyślnie wysłana Wysłanie sugestii nie powiodło się (%s) Wyświetl ukryte wydarzenia na linii czasowej (edytowano) @@ -1058,12 +1058,12 @@ Zaakceptowałeś(-łaś) Żądanie weryfikacji wysłane Żądanie weryfikacji - Zweryfikuj tą sesję + Zweryfikuj tę sesję Zeskanuj kod z urządzenia innego użytkownika aby bezpiecznie zweryfikować siebie nawzajem Zeskanuj ich kod Nie można zeskanować Jeżeli nie jesteś z tą osobą, zamiast tego porównaj emoji - Zweryfikuj porównując emoji + Zweryfikuj porównując emotikony Zweryfikuj %s Zweryfikowano %s Oczekiwanie na %s… @@ -1099,7 +1099,7 @@ Aktywować szyfrowanie\? Raz włączone szyfrowanie w pokoju nie może zostać wyłączone. Wiadomości wysłane w zaszyfrowanym pokoju nie są widziane przez serwer, a jedynie przez uczestników w pokoju. Aktywowanie szyfrowania może uniemożliwić wielu botom i mostkom prawidłowe działanie. Aktywuj szyfrowanie - Aby być bezpiecznym, zweryfikuj %s poprzez sprawdzenie jednorazowego kodu. + Aby zachować bezpieczeństwo, zweryfikuj %s poprzez sprawdzenie jednorazowego kodu. Aby być bezpiecznym, zrób to osobiście lub użyj innej metody komunikacji. Porównaj unikalny ciąg emoji, upewniając się, że pojawiają się w identycznym porządku. Porównaj kod wyświetlany na ekranie innego użytkownika. @@ -1120,7 +1120,7 @@ Wyloguj z tej sesji Brak dostępnej informacji o kryptografii Ta sesja jest zaufana dla bezpiecznej wymiany wiadomości, ponieważ ją zweryfikowałeś(-łaś): - Zweryfikuj tą sesję aby oznaczyć ją jako zaufaną i przyznać jej dostęp do zaszyfrowanych wiadomości. Jeżeli nie logowałeś(-łaś) się do tej sesji, twoje konto mogło zostać naruszone: + Zweryfikuj tę sesję aby oznaczyć ją jako zaufaną i przyznać jej dostęp do zaszyfrowanych wiadomości. Jeżeli nie logowałeś(-łaś) się do tej sesji, twoje konto mogło zostać zaatakowane: %d aktywna sesja %d aktywne sesje @@ -1330,12 +1330,12 @@ Hasło odzyskiwania Weryfikacja anulowana Weryfikacja anulowana. Możesz rozpocząć jej proces ponownie. - Jedno z poniższych mogło zostać skompromitowane: + Jedno z poniższych może być zagrożone: \n -\n-Twoje hasło -\n-Twój serwer domowy -\n-To urządzenie albo inne urządzenie -\n-Połączenie internetowe używane przez urządzenie +\n- Twoje hasło +\n- Twój serwer domowy +\n- To lub drugie urządzenie +\n- Połączenie internetowe używane przez dowolne z urządzeń \n \nZalecamy natychmiastową zmianę Twojego hasła oraz klucza odzyskiwania w Ustawieniach. Jeżeli anulujesz, nie będziesz w stanie czytać zaszyfrowanych wiadomości na nowym urządzeniu, a inni użytkownicy nie będą mu ufali @@ -1388,7 +1388,7 @@ Zablokuj wszystkich nie będących członkami %s przed dołączeniem do tego pokoju Ukryj zaawansowane Pokaż zaawansowane - Nie można znaleźć właściwego serwera domowego. Zweryfikuj swój identyfikator + Nie można znaleźć właściwego serwera domowego. Sprawdź swój identyfikator To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \"@user:homeserver.org\" Jeżeli nie pamiętasz hasła, cofnij się aby je zresetować. Matrix ID @@ -1492,7 +1492,7 @@ Włącz \"Zezwalaj na integracje\" w Ustawieniach żeby to zrobić. Integracje są zablokowane To zastąpi obecny Klucz bądź Hasło. - Wygeneruj nowy Klucz Bezpieczeństwa albo Hasło dla istniejącej kopii zapasowej. + Wygeneruj nowy klucz bezpieczeństwa albo hasło dla istniejącej kopii zapasowej. Zabezpiecza przeciwko utracie dostępu do zaszyfrowanych wiadomości oraz danych poprzez zapisanie zaszyfrowanych kluczy na Twoim serwerze. Powiadomienie zostało kliknięte! Proszę kliknąć na powiadomieniu, Jeżeli nie widzisz powiadomienia, sprawdź ustawienia systemowe. @@ -1649,7 +1649,7 @@ Mój kod Udostępnij mój kod Zeskanuj kod QR - Nie możemy zaprosić użytkowników. Zweryfikuj osoby, które chcesz zaprosić i spróbuj ponownie. + Nie udało się zaprosić użytkowników. Sprawdź osoby, które chcesz zaprosić i spróbuj ponownie. Zaproszenia wysłane do %1$s i jeszcze jednej osoby Zaproszenia wysłane do %1$s i %2$d innych osób @@ -1985,7 +1985,7 @@ Udostępnij link Zaproś przez nazwę użytkownika lub email Zaproś przez email - Aktualnie jesteś tylko Ty. %s będzie jeszcze lepsza kiedy dołączą inni. + Aktualnie jesteś tu tylko ty. %s będzie jeszcze lepszą przestrzenią, gdy dołączą do niej inni. Zaproś do %s Zaproś osoby Zaproś osoby do Twojej przestrzeni @@ -2127,7 +2127,7 @@ Limit wielkości pliku na serwerze Wersja serwera Nazwa serwera - Zweryfikuj zgodność wyświetlonych emotikon + Zamiast tego, zweryfikuj porównując emotikony Zeskanuj za pomocą tego urządzenia Zeskanuj kod Twoim drugim urządzeniem lub przełącz się i zeskanuj za pomocą tego urządzenia Głos @@ -2311,8 +2311,8 @@ Zastąp kolor wyświetlanej nazwy Posiadam już konto - Połącz się z każdym. - Ty jesteś w kontroli. + Bezpieczna komunikacja. + Masz wszystko pod kontrolą. Przejmij swoje konwersacje. By odkryć istniejące kontakty, musisz najpierw przesłać swoje dane kontaktowe (adresy e-mail i numer telefonu) do serwera tożsamości. Przed wysłaniem Twoje dane zostaną zaszyfrowane w celu zachowania prywatności. Uzyskaj pomoc w korzystaniu z ${app_name} @@ -2392,12 +2392,12 @@ Społeczności Zespoły Przyjaciele i rodzina - Pomożemy Ci się połączyć + Pomożemy Ci nawiązać kontakt Z kim będziesz najczęściej rozmawiać\? - Szyfrowane od-końca-do-końca i nie wymaga numeru telefonu. Brak reklam i dataminingu. + Szyfrowane od-końca-do-końca, bez konieczności podawania numeru telefonu. Zero reklam i dataminingu. Wybierz, gdzie prowadzone są Twoje rozmowy, dając Ci kontrolę i niezależność. Połączenie przez sieć Matrix. Bezpieczna i niezależna komunikacja, która zapewnia ten sam poziom prywatności, co rozmowa twarzą w twarz we własnym domu. - Wiadomości dla Twojego zespołu. + Komunikacja dla Twojego zespołu. Położenie Zagadnienia prawne Już przeglądasz ten wątek! @@ -2521,7 +2521,7 @@ Każdy w przestrzeni nadrzędnej będzie mógł znaleźć ten pokój i dołączyć do niego — nie ma potrzeby ręcznego zapraszania wszystkich. W każdej chwili możesz to zmienić w ustawieniach pokoju. Automatycznie aktualizuj nadrzędną przestrzeń Twój system automatycznie wyśle dzienniki, gdy wystąpi błąd niemożności odszyfrowania - Błędy automatycznego deszyfrowania raportów. + Automatycznie zgłaszaj błędy deszyfrowania. Opuść pokój o podanym identyfikatorze (lub aktualny pokój, jeśli null) Udostępnili swoją lokalizację Powiadom cały pokój @@ -2697,8 +2697,8 @@ Nie można wczytać mapy. \nTen serwer macierzysty może nie być skonfigurowany do wyświetlania map. Otwórz ustawienia - Aby zapewnić najlepsze bezpieczeństwo, zweryfikuj swoje sesje i wyloguj się z każdej sesji, której już nie rozpoznajesz lub której już nie używasz. - Inne sesje + Aby zapewnić najlepsze bezpieczeństwo, zweryfikuj swoje sesje i wyloguj się z każdej sesji, której już nie rozpoznajesz lub której już nie używasz. + Inne sesje Sesje Lista otwartych przestrzeni Utwórz nową rozmowę lub pokój @@ -2718,4 +2718,18 @@ Utwórz pokój Zacznij rozmawiać Wszystkie rozmowy + Nie zweryfikowano · Ostatnia aktywność %1$s + Zweryfikowano · Ostatnia aktywność %1$s + Pokaż wszystkie (%1$d) + Pokaż szczegóły + Zweryfikuj sesję + Niezweryfikowana sesja + Zweryfikowana sesja + Nieznany typ urządzenia + Komputer + Przeglądarka + Urządzenie przenośne + Niestety, ten pokój nie został znaleziony. +\nSpróbuj ponownie później.%s + Zaproszenia diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index 23dd6ae75f..817c7646df 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -1,6 +1,6 @@ - convite de %s + Convite de %s %1$s convidou %2$s %1$s convidou você %1$s juntou-se à sala @@ -418,7 +418,7 @@ Des-definir como endereço principal Erro de decriptação Nome público - ID de sessão + ID de sessão Chave de sessão Exportar chaves de sala E2E Exportar chaves de sala @@ -2320,7 +2320,7 @@ Enviar imagens e vídeos Abrir câmera Seu sistema vai automaticamente enviar logs quando um erro incapaz de decriptar ocorre - Auro Reportar Erros de Decriptação. + Auto Reportar Erros de Decriptação. Sobrepor cor de nome de exibição Eu já tenho uma conta Mensageria segura. @@ -2477,7 +2477,7 @@ Backup tem uma assinatura válida desta(e) usuária(o). Atualizada %1$s atrás Implementação tempoária: locais persistem em histórico de sala - Habilitar Compartilhament de Localização Ao Vivo + Habilitar Compartilhamento de Localização Ao Vivo %1$s restando Ao vivo até %1$s Ver localização ao vivo @@ -2499,7 +2499,7 @@ Endpoint Gateway Ativar compartilhamento de localização - Compartilhamento de localização em tempo real + Compartilhamento de localização ao vivo Gateway atual: %s Não foi possível encontrar o endpoint. Endpoint atual: %s @@ -2538,7 +2538,7 @@ Nome de Usuária(o) / Email / Telefone Você é um/uma humano(a)\? Siga as instruções enviadas para %s - Reset de senha + Senha resettada Esqueceu senha Reenviar email Não recebeu um email\? @@ -2601,8 +2601,8 @@ Abrir configurações Todos os Chats Mostrar Todas Sessões (V2, WIP) - Para a melhor segurança, verifique suas sessões e faça signout de qualquer sessão que você não reconhece ou usa mais. - Outras sessões + Para a melhor segurança, verifique suas sessões e faça signout de qualquer sessão que você não reconhece ou usa mais. + Outras sessões Sessões Abrir lista de espaços Criar uma nova conversa ou sala @@ -2619,4 +2619,53 @@ Explorar Salas Criar Sala Começar Chat + Não-verificada · Última atividade %1$s + Verificada · Última atividade %1$s + Ver Todas (%1$d) + Visualizar Detalhes + Verificar Sessão + Sessão não-verificada + Sessão verificada + Tipo de dispositivo desconhecido + Desktop + Mobile + Web + Desculpe, esta sala não tem sido encontrada. +\nPor favor retente mais tarde.%s + Convites + Teste aí + Toque na direita topo para ver a opção para feedback. + Dar Feedback + Acessar seus Espaços (direito fundo) mais rápido e fácio que jamais antes. + Acessar Espaços + Para simplificar seu ${app_name}, abas são agora opcionais. Gerencie-as usando o menu direito topo. + Boas-vindas a uma nova visão! + Isto é onde suas mensagens não-lidas vão aparecer, quando você tiver algumas. + Nada a reportar. + O app de chat seguro tudo-em-um para equipes, amigas(os) e organizações. Crie um chat, ou junte-se a uma sala existe, para começar. + Boas-vindas a ${app_name}, +\n%s. + Espaços são uma nova maneira de agrupar salas e pessoas. Adicione uma sala existente, ou crie uma nova, usando o botão direito fundo. + %s +\nestá parecendo um pouco vazio. + + Considere fazer signout de sessões antigas (%1$d dia ou mais) que você não usa mais. + Considere fazer signout de sessões antigas (%1$d dias ou mais) que você não usa mais. + + Sessões inativas + Verificar ou fazer signout de sessões não-verificadas. + Sessões não-verificadas + Melhore a segurança de sua conta ao seguir estas recomendações. + Recomendações de segurança + + Inativa(o) por %1$d+ dia (%2$s) + Inativa(o) por %1$d+ dias (%2$s) + + Isto é onde suas novas requisições e convites vão estar. + Nada novo. + Espaços são uma nova maneira de agrupar salas e pessoas. Crie um espaço para começar. + Nenhum espaço ainda. + Colapsar filhos de %s + Expandir filhos de %s + Mudar Espaço diff --git a/library/ui-strings/src/main/res/values-pt/strings.xml b/library/ui-strings/src/main/res/values-pt/strings.xml index 4daaef83b0..87b6297b2b 100644 --- a/library/ui-strings/src/main/res/values-pt/strings.xml +++ b/library/ui-strings/src/main/res/values-pt/strings.xml @@ -246,7 +246,7 @@ Note que esta acção irá reiniciar a aplicação e poderá levar algum tempo.< Erro de decifragem Nome do dispositivo - ID do dispositivo + ID do dispositivo Chave do dispositivo Exportar chaves E2E da sala Exportar chaves de sala diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index 4852be1f82..7c9d073035 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -432,7 +432,7 @@ Сбросить основной адрес Ошибка дешифровки Публичное имя - ID сессии + ID сессии Ключ сессии Экспорт E2E ключей комнаты Экспорт ключей комнаты @@ -2660,8 +2660,8 @@ Не удалось загрузить карту \nВозможно, этот домашний сервер не настроен для отображения карт. Все беседы - Для лучшей безопасности заверьте свои сессии и выйдите из тех, которые более не признаёте или не используете. - Другие сессии + Для лучшей безопасности заверьте свои сессии и выйдите из тех, которые более не признаёте или не используете. + Другие сессии Сессии Создать беседу или комнату Показать все сессии (V2, в разработке) @@ -2678,4 +2678,19 @@ Обзор комнат Начать беседу Создать комнату - \ No newline at end of file + Посмотреть все (%1$d) + Повысьте безопасность учётной записи, следуя этим рекомендациям. + Заверенная · Последняя активность %1$s + Незаверенная сессия + Заверенная сессия + Неизвестный тип устройства + Компьютер + Мобильный + Незаверенная · Последняя активность %1$s + Рекомендации по безопасности + Незаверенные сессии + Неактивные сессии + Добро пожаловать в ${app_name}, +\n%s. + Оставить отзыв + diff --git a/library/ui-strings/src/main/res/values-sk/strings.xml b/library/ui-strings/src/main/res/values-sk/strings.xml index 68663b3b9c..9eb22e3ae3 100644 --- a/library/ui-strings/src/main/res/values-sk/strings.xml +++ b/library/ui-strings/src/main/res/values-sk/strings.xml @@ -388,7 +388,7 @@ Vzhľad Chyba dešifrovania Verejné meno - ID relácie + ID relácie Kľúč relácie Exportovať šifrovacie kľúče miestnosti Exportovať kľúče miestnosti @@ -2651,8 +2651,8 @@ Otvoriť nastavenia Všetky konverzácie Zobraziť všetky relácie (V2, WIP) - V záujme čo najlepšieho zabezpečenia overte svoje relácie a odhláste sa z každej relácie, ktorú už nepoznáte alebo nepoužívate. - Iné relácie + V záujme čo najlepšieho zabezpečenia overte svoje relácie a odhláste sa z každej relácie, ktorú už nepoznáte alebo nepoužívate. + Iné relácie Relácie Otvoriť zoznam priestorov Vytvoriť novú konverzáciu alebo miestnosť @@ -2669,4 +2669,55 @@ Preskúmať miestnosti Vytvoriť miestnosť Začať konverzáciu + Neoverené - Posledná aktivita %1$s + Overené - Posledná aktivita %1$s + Zobraziť všetky (%1$d) + Zobraziť podrobnosti + Overiť reláciu + Neoverená relácia + Overená relácia + Neznámy typ zariadenia + Stolný počítač + Web + Mobil + Je nám ľúto, táto miestnosť nebola nájdená. +\nProsím, skúste to neskôr.%s + Pozvánky + Vyskúšajte si to + Ťuknutím na položku vpravo hore zobrazíte možnosť spätnej väzby. + Poskytnite spätnú väzbu + Získajte prístup k svojim priestorom (vľavo dole) rýchlejšie a jednoduchšie ako kedykoľvek predtým. + Prístup k priestorom + Pre zjednodušenie vašej aplikácie ${app_name}, sú teraz karty voliteľné. Spravujte ich pomocou ponuky vpravo hore. + Vitajte v novom zobrazení! + Tu sa zobrazia neprečítané správy, ak nejaké máte. + Nič, o čom by bolo potrebné podať správu. + Kompletná zabezpečená aplikácia na komunikáciu pre tímy, priateľov a organizácie. Začnite konverzáciu alebo sa pridajte k existujúcej miestnosti. + Vitajte v aplikácii ${názov_aplikácie}, +\n%s. + Priestory sú novým spôsobom zoskupovania miestností a ľudí. Pomocou tlačidla vpravo dole môžete pridať existujúcu miestnosť alebo vytvoriť novú. + %s +\nvyzerá trochu prázdne. + + Zvážte odhlásenie zo starých relácií (%1$d deň alebo viac), ktoré už nepoužívate. + Zvážte odhlásenie zo starých relácií (%1$d dni alebo viac), ktoré už nepoužívate. + Zvážte odhlásenie zo starých relácií (%1$d dní alebo viac), ktoré už nepoužívate. + + Neaktívne relácie + Overte alebo sa odhláste z neoverených relácií. + Neoverené relácie + Zlepšite zabezpečenie svojho účtu dodržiavaním týchto odporúčaní. + Bezpečnostné odporúčania + + Neaktívny už %1$d+ deň (%2$s) + Neaktívny už %1$d+ dni (%2$s) + Neaktívny už %1$d+ dní (%2$s) + + Tu sa budú nachádzať vaše nové žiadosti a pozvánky. + Nič nové. + Priestory sú novým spôsobom zoskupovania miestností a ľudí. Vytvorte si priestor a začnite. + Zatiaľ žiadne priestory. + Zbaliť %s podpriestory + Rozbaliť %s podpriestory + Zmeniť priestor diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index 8fdf4ee310..a6af0a4921 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -431,7 +431,7 @@ Temë Gabim shfshehtëzimi Emër publik - ID Sesioni + ID Sesioni Kyç sesioni Eksporto kyçe dhome E2E Eksporto kyçe dhome diff --git a/library/ui-strings/src/main/res/values-sv/strings.xml b/library/ui-strings/src/main/res/values-sv/strings.xml index 025713272c..30b63c213c 100644 --- a/library/ui-strings/src/main/res/values-sv/strings.xml +++ b/library/ui-strings/src/main/res/values-sv/strings.xml @@ -918,7 +918,7 @@ Sätt upp på den här enheten Generera en ny säkerhetskopia eller sätt en ny lösenfras för din existerande säkerhetskopia. Detta är experimentella funktioner som kan gå sönder på oväntade sätt. Använd varsamt. - Sessions-ID + Sessions-ID Sessionsnyckel Exportera krypteringsnycklar Exportera rumsnycklar diff --git a/library/ui-strings/src/main/res/values-te/strings.xml b/library/ui-strings/src/main/res/values-te/strings.xml index 5ed2462ce8..0154d54c2e 100644 --- a/library/ui-strings/src/main/res/values-te/strings.xml +++ b/library/ui-strings/src/main/res/values-te/strings.xml @@ -260,7 +260,7 @@ ప్రధాన చిరునామాగా సెట్ చేయండి పరికరం పేరు - పరికరం ID + పరికరం ID పరికరం కీ E2E గది కీలను ఎగుమతి చేయండి diff --git a/library/ui-strings/src/main/res/values-tr/strings.xml b/library/ui-strings/src/main/res/values-tr/strings.xml index c097bfce6a..1f0e5be153 100644 --- a/library/ui-strings/src/main/res/values-tr/strings.xml +++ b/library/ui-strings/src/main/res/values-tr/strings.xml @@ -376,7 +376,7 @@ Tema Çözme hatası Görünür Ad - Oturum kimliği + Oturum kimliği Oturum anahtarı E2E Oda anahtarlarını dışa aktar Oda anahtarlarını dışa aktar diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index 47f15c9a27..3e511f8459 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -354,7 +354,7 @@ Зробити не основною адресою Помилка розшифрування Загальнодоступна назва - ID сеансу + ID сеансу Ключ сеансу Експортувати E2E ключі кімнати Експортувати ключі кімнати @@ -2701,8 +2701,8 @@ Відкрити налаштування Усі бесіди Показати всі сеанси (V2, WIP) - Для найкращої безпеки перевірте свої сеанси та вийдіть з усіх сеансів, які ви більше не розпізнаєте або не використовуєте. - Інші сеанси + Для найкращої безпеки перевірте свої сеанси та вийдіть з усіх сеансів, які ви більше не розпізнаєте або не використовуєте. + Інші сеанси Сеанси Відкрити список кімнат Створити нову розмову або кімнату @@ -2719,4 +2719,57 @@ Знайти кімнати Створити кімнату Розпочати бесіду + Не звірений · Остання активність %1$s + Звірений · Остання активність %1$s + Переглянути всі (%1$d) + Переглянути подробиці + Звірити сеанс + Не звірений сеанс + Звірений сеанс + Невідомий тип пристрою + Комп\'ютер + Браузер + Мобільний + Перепрошуємо, цю кімнату не знайдено. +\nСпробуйте пізніше.%s + Запрошення + Спробувати + Клацніть праворуч вгорі, щоб побачити опцію відгуку. + Надіслати відгук + Отримуйте доступ до своїх просторів (унизу праворуч) швидше та легше, ніж раніше. + Доступ до просторів + Щоб спростити ваш ${app_name}, вкладки тепер необов’язкові. Керуйте ними у верхньому правому меню. + Вітаємо в новому вигляді! + Тут з\'являтимуться ваші непрочитані повідомлення, якщо вони є. + Немає про що звітувати. + Універсальний безпечний застосунок для спілкування з командами, друзями й організаціями. Створіть бесіду або приєднайтеся до наявної кімнати, щоб розпочати. + Вітаємо в ${app_name}, +\n%s. + Простори – це новий спосіб групувати кімнати та людей. Додайте наявну кімнату або створіть нову, використовуючи кнопку внизу праворуч. + %s +\nмає дещо порожній вигляд. + + Зважте потребу вийти зі старих сеансів (%1$d день або більше), який ви більше не використовуєте. + Зважте потребу вийти зі старих сеансів (%1$d дні або більше), які ви більше не використовуєте. + Зважте потребу вийти зі старих сеансів (%1$d днів або більше), які ви більше не використовуєте. + Зважте потребу вийти зі старих сеансів (%1$d днів або більше), які ви більше не використовуєте. + + Неактивні сеанси + Звірити або вийти з не звірених сеансів. + Не звірений сеанс + Удоскональте безпеку свого облікового запису, дотримуючись цих порад. + Поради щодо безпеки + + Без активності %1$d+ день (%2$s) + Без активності %1$d+ дні (%2$s) + Без активності %1$d+ днів (%2$s) + Без активності %1$d+ днів (%2$s) + + Тут з\'являтимуться нові запити та запрошення. + Нічого нового. + Простори – це новий спосіб групувати кімнати та людей. Створіть простір, щоб розпочати. + Ще немає просторів. + Згорнути дочірні елементи %s + Розгорнути дочірні елементи %s + Змінити простір diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 2803128843..c6dc97f782 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -594,7 +594,7 @@ Hủy tài khoản Xem lại ngay Chìa khóa phiên - Mã phiên + Mã phiên Tên công khai Lỗi giải mã Những chức năng này mang tính thí nghiệm có thể còn nhiều lỗi. Lưu ý khi dùng. diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 6f7151167f..db1dab92e2 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -242,7 +242,7 @@ 你的密码已更新 解密错误 公开名称 - 会话 ID + 会话 ID 会话密钥 导入 已验证 @@ -1682,7 +1682,7 @@ "话题: " 添加一个话题 %s让人们知道此房间是关于什么的。 - 这是你和 %s 的私聊消息历史记录的开始。 + 这是你和%s的私聊消息历史的开始。 这是此对话的开始。 这是 %s 的开始。 导出审计 @@ -2500,7 +2500,7 @@ 若启用,即使正在使用应用,你也会对其他用户显示为离线状态。 离线模式 在场 - 动画图片一出现就在时间轴中播放 + 动画图片一出现就在时间线中播放 Threads Beta ${app_name} needs to perform a clear cache to be up to date, 原因如下: \n%s @@ -2551,8 +2551,8 @@ 打开设置 全部聊天 显示全部会话(V2, WIP) - 为获得最佳安全性,请验证你的会话,并从任何你不认识或不再使用的会话登出。 - 其他会话 + 为获得最佳安全性,请验证你的会话,并从任何你不认识或不再使用的会话登出。 + 其他会话 会话 打开空间列表 创建新对话或房间 @@ -2569,4 +2569,39 @@ 探索房间 创建房间 开始聊天 + 抱歉,未发现此房间。 +\n请晚些重试。%s + 未验证 · 上次活跃 %1$s + 已验证 · 上次活跃 %1$s + 查看全部(%1$d) + 查看详情 + 验证会话 + 未验证的会话 + 已验证的会话 + 未知的设备类型 + 邀请 + 移动设备 + Web + 桌面 + 更改空间 + 尚无空间。 + 没有新的东西。 + 你的新请求和邀请会在这里。 + + %1$d+天不活跃(%2$s) + + 安全建议 + 按照这些建议改善你的账户安全。 + 未验证的会话 + 验证未验证的会话或从之登出。 + 不活跃的会话 + + 请考虑从不再使用的旧会话(%1$d天或更久)登出。 + + 欢迎来到${app_name}, +\n%s。 + 未读消息会在这里显示。 + 提供反馈 + 点击右上角查看反馈选项。 + 试用 diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 93b4a8d4c6..78caa2cc2e 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -469,7 +469,7 @@ 主題 解密錯誤 公開名稱 - 工作階段 ID + 工作階段 ID 工作階段金鑰 匯出聊天室的端到端加密金鑰 匯出聊天室的加密金鑰 @@ -2551,8 +2551,8 @@ 開啟設定 所有聊天 顯示所有工作階段 (V2, WIP) - 為了取得最佳安全性,請驗證您的工作階段並登出任何您無法識別或不再使用的工作階段。 - 其他工作階段 + 為了取得最佳安全性,請驗證您的工作階段並登出任何您無法識別或不再使用的工作階段。 + 其他工作階段 工作階段 開啟空間清單 建立新的對話或聊天室 @@ -2569,4 +2569,51 @@ 探索聊天室 建立聊天室 開始聊天 + 未驗證 · 最後活動 %1$s + 已驗證 · 最後活動 %1$s + 檢視全部 (%1$d) + 檢視詳細資訊 + 驗證工作階段 + 未驗證的工作階段 + 已驗證的工作階段 + 未知的裝置類型 + 桌面 + 網頁 + 行動裝置 + 抱歉,找不到此聊天室。 +\n請稍後再試。%s + 邀請 + 試試看 + 輕點右上角來檢視回饋選項。 + 給予回饋 + 存取您的空間(右下角)比以往任何時候都更快且更輕鬆。 + 存取空間 + 為了簡化您的 ${app_name},分頁現在是選擇性的。使用右上角的選單管理它們。 + 歡迎使用新的檢視! + 當您有一些未讀的訊息時,這裡會顯示您的未讀訊息。 + 沒有要回報的東西。 + 適用於團隊、朋友與組織的多合一安全聊天應用程式。建立聊天室,或加入一個既有的聊天室。 + 歡迎使用 ${app_name}, +\n%s. + 空間是一種為聊天室與人們分組的新方式。使用右下角的按鈕新增既有的聊天室或建立新的。 + %s +\n看起來有點空。 + + 考慮登出您不再使用的舊工作階段(%1$d天或更久)。 + + 不活躍的工作階段 + 驗證或從未驗證的工作階段登出。 + 未驗證的工作階段 + 按照這些建議提高您的帳號安全性。 + 安全建議 + + 不活躍 %1$d+ 天 (%2$s) + + 這是您的新請求與邀請的所在。 + 沒有新東西。 + 空間是一種對聊天室與人們分組的新方式。建立空間以開始。 + 尚無空間。 + 折疊 %s 個子空間 + 展開 %s 個子空間 + 變更空間 diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index df0e10627a..d8f6222acf 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -139,9 +139,12 @@ All Chats Start Chat Create Room + Change Space Explore Rooms - Expand space children - Collapse space children + + Expand %s children + + Collapse %s children @@ -436,15 +439,28 @@ Activity A - Z + Enable new layout + A simplified Element with optional tabs + + Enable deferred DMs + Create DM only on first message + Invites Low priority "System Alerts" Suggested Rooms + + No spaces yet. + Spaces are a new way to group rooms and people. Create a space to get started. + Invites + Nothing new. + This is where your new requests and invites will be. + Conversations Matrix contacts only @@ -1199,7 +1215,6 @@ Decryption error Public name - Session ID Session key Export E2E room keys @@ -1389,6 +1404,7 @@ Changes your avatar in this current room only On/Off markdown To fix Matrix Apps management + Open the developer tools screen Displays information about a user Markdown has been enabled. @@ -2349,8 +2365,8 @@ Manage Sessions Sign out of this session Sessions - Other sessions - For best security, verify your sessions and sign out from any session that you don’t recognize or use anymore. + Other sessions + For best security, verify your sessions and sign out from any session that you don’t recognize or use anymore. Server name Server version @@ -3217,14 +3233,18 @@ Unknown device type Verified session Unverified session - Your current session is ready for secure messaging. - Verify your current session for enhanced secure messaging. + Your current session is ready for secure messaging. + This session is ready for secure messaging. + Verify your current session for enhanced secure messaging. + Verify or sign out from this session for best security and reliability. Verify Session View Details - Current Session View All (%1$d) + Verified · Last activity %1$s + Unverified · Last activity %1$s + Unverified · Your current session Inactive for %1$d+ day (%2$s) @@ -3239,5 +3259,62 @@ Consider signing out from old sessions (%1$d day or more) that you don’t use anymore. Consider signing out from old sessions (%1$d days or more) that you don’t use anymore. + Current Session + Session + Device + + Last activity %1$s + Filter + All sessions + Verified + Ready for secure messaging + Unverified + Not ready for secure messaging + Inactive + + Inactive for %1$d day or longer + Inactive for %1$d days or longer + + Filter + Verified + For best security, sign out from any session that you don’t recognize or use anymore. + Unverified + Verify your sessions for enhanced secure messaging or sign out from those you don’t recognize or use anymore. + Inactive + + Consider signing out from old sessions (%1$d day or more) you don’t use anymore. + Consider signing out from old sessions (%1$d days or more) you don’t use anymore. + + No verified sessions found. + No unverified sessions found. + No inactive sessions found. + Clear Filter + Session details + Application, device, and activity information. + Session name + Session ID + Last activity + IP address + + + %s\nis looking a little empty. + + Spaces are a new way to group rooms and people. Add an existing room, or create a new one, using the bottom-right button. + + Welcome to ${app_name},\n%s. + The all-in-one secure chat app for teams, friends and organisations. Create a chat, or join an existing room, to get started. + Nothing to report. + This is where your unread messages will show up, when you have some. + + Welcome to a new view! + + To simplify your ${app_name}, tabs are now optional. Manage them using the top-right menu. + Access Spaces + + Access your Spaces (bottom-right) faster and easier than ever before. + Give Feedback + + Tap top right to see the option to feedback. + Try it out diff --git a/library/ui-styles/src/debug/res/menu/menu_debug.xml b/library/ui-styles/src/debug/res/menu/menu_debug.xml index c58a29db8f..ac98ce8e2c 100644 --- a/library/ui-styles/src/debug/res/menu/menu_debug.xml +++ b/library/ui-styles/src/debug/res/menu/menu_debug.xml @@ -14,6 +14,7 @@ android:id="@+id/menuDebug2" android:icon="@drawable/ic_debug_icon" android:title="Send" - app:showAsAction="always" /> + app:showAsAction="always" + tools:ignore="AlwaysShowAction" /> - \ No newline at end of file + diff --git a/library/ui-styles/src/main/res/values-h720dp/dimens.xml b/library/ui-styles/src/main/res/values-h720dp/dimens.xml index 1a7791720d..2a7b12cf2f 100644 --- a/library/ui-styles/src/main/res/values-h720dp/dimens.xml +++ b/library/ui-styles/src/main/res/values-h720dp/dimens.xml @@ -2,4 +2,8 @@ 0.05 0.40 - \ No newline at end of file + + 16dp + 40dp + 46dp + diff --git a/library/ui-styles/src/main/res/values/colors.xml b/library/ui-styles/src/main/res/values/colors.xml index 01af740d43..3d6bc91f2e 100644 --- a/library/ui-styles/src/main/res/values/colors.xml +++ b/library/ui-styles/src/main/res/values/colors.xml @@ -141,6 +141,7 @@ #0DBD8B + #0F0DBD8B #17191C #FF4B55 #0FFF4B55 diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml index 53f1044a12..758dd6e978 100644 --- a/library/ui-styles/src/main/res/values/dimens.xml +++ b/library/ui-styles/src/main/res/values/dimens.xml @@ -74,4 +74,9 @@ 112dp + + + 8dp + 16dp + 28dp diff --git a/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml b/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml deleted file mode 100644 index f0807f89c6..0000000000 --- a/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/library/ui-styles/src/main/res/values/stylable_other_sessions_security_recommendation_view.xml b/library/ui-styles/src/main/res/values/stylable_other_sessions_security_recommendation_view.xml new file mode 100644 index 0000000000..6a46132b13 --- /dev/null +++ b/library/ui-styles/src/main/res/values/stylable_other_sessions_security_recommendation_view.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/stylable_session_overview_entry_view.xml b/library/ui-styles/src/main/res/values/stylable_session_overview_entry_view.xml new file mode 100644 index 0000000000..d3884f247d --- /dev/null +++ b/library/ui-styles/src/main/res/values/stylable_session_overview_entry_view.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/stylable_sessions_list_header_view.xml b/library/ui-styles/src/main/res/values/stylable_sessions_list_header_view.xml new file mode 100644 index 0000000000..d3b931e44a --- /dev/null +++ b/library/ui-styles/src/main/res/values/stylable_sessions_list_header_view.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/styles_devices_management.xml b/library/ui-styles/src/main/res/values/styles_devices_management.xml index 2a63c2ed36..6b42b85ffd 100644 --- a/library/ui-styles/src/main/res/values/styles_devices_management.xml +++ b/library/ui-styles/src/main/res/values/styles_devices_management.xml @@ -1,12 +1,17 @@ + + diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt index 8be8e83569..a6b4cc98a6 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt @@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.ReadReceipt import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -46,6 +47,13 @@ class FlowRoom(private val room: Room) { } } + fun liveLocalRoomSummary(): Flow> { + return room.getLocalRoomSummaryLive().asFlow() + .startWith(room.coroutineDispatchers.io) { + room.localRoomSummary().toOptional() + } + } + fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow> { return room.membershipService().getRoomMembersLive(queryParams).asFlow() .startWith(room.coroutineDispatchers.io) { diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt index f22cfa369a..80ed311901 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt @@ -72,7 +72,7 @@ class FlowSession(private val session: Session) { } fun liveMyDevicesInfo(): Flow> { - return session.cryptoService().getLiveMyDevicesInfo().asFlow() + return session.cryptoService().getMyDevicesInfoLive().asFlow() .startWith(session.coroutineDispatchers.io) { session.cryptoService().getMyDevicesInfo() } diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 7b06edb530..5c800f720e 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -60,7 +60,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.4.36\"" + buildConfigField "String", "SDK_VERSION", "\"1.5.2\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index a78953caac..b179c6027e 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -36,6 +36,7 @@ import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixConfiguration +import org.matrix.android.sdk.api.SyncConfig import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.registration.RegistrationResult import org.matrix.android.sdk.api.session.Session @@ -103,7 +104,8 @@ class CommonTestHelper internal constructor(context: Context) { context, MatrixConfiguration( applicationFlavor = "TestFlavor", - roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider() + roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider(), + syncConfig = SyncConfig(longPollTimeout = 5_000L), ) ) } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt index ba1afd4758..48cfbebe5b 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt @@ -21,6 +21,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper +import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.time.DefaultClock import kotlin.random.Random @@ -37,6 +38,7 @@ internal class CryptoStoreHelper { userId = "userId_" + Random.nextInt(), deviceId = "deviceId_sample", clock = DefaultClock(), + myDeviceLastSeenInfoEntityMapper = MyDeviceLastSeenInfoEntityMapper() ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 251c13ccbf..f883295495 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -676,8 +676,8 @@ class E2eeSanityTests : InstrumentedTest { assertEquals("Decimal code should have matched", oldCode, newCode) // Assert that devices are verified - val newDeviceFromOldPov: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceNewSession.sessionParams.deviceId) - val oldDeviceFromNewPov: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.sessionParams.deviceId) + val newDeviceFromOldPov: CryptoDeviceInfo? = aliceSession.cryptoService().getCryptoDeviceInfo(aliceSession.myUserId, aliceNewSession.sessionParams.deviceId) + val oldDeviceFromNewPov: CryptoDeviceInfo? = aliceSession.cryptoService().getCryptoDeviceInfo(aliceSession.myUserId, aliceSession.sessionParams.deviceId) Assert.assertTrue("new device should be verified from old point of view", newDeviceFromOldPov!!.isVerified) Assert.assertTrue("old device should be verified from new point of view", oldDeviceFromNewPov!!.isVerified) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index 8cb38ddc87..ef3fdfeeda 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -193,7 +193,7 @@ class XSigningTest : InstrumentedTest { fail("Bob should see the new device") } - val bobSecondDevicePOVFirstDevice = bobSession.cryptoService().getDeviceInfo(bobUserId, bobSecondDeviceId) + val bobSecondDevicePOVFirstDevice = bobSession.cryptoService().getCryptoDeviceInfo(bobUserId, bobSecondDeviceId) assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice) // Manually mark it as trusted from first session diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt index c2e74abc59..1bffbeeeaa 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt @@ -521,9 +521,9 @@ class SASTest : InstrumentedTest { testHelper.await(bobSASLatch) // Assert that devices are verified - val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(bobUserId, bobDeviceId) + val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = aliceSession.cryptoService().getCryptoDeviceInfo(bobUserId, bobDeviceId) val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = - bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId) + bobSession.cryptoService().getCryptoDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId) assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified) assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt index 893e90fb3e..7119563617 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt @@ -70,4 +70,8 @@ data class MatrixConfiguration( * List of network interceptors, they will be added when building an OkHttp client. */ val networkInterceptors: List = emptyList(), + /** + * Sync configuration. + */ + val syncConfig: SyncConfig = SyncConfig(), ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/SyncConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/SyncConfig.kt new file mode 100644 index 0000000000..a9753e2407 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/SyncConfig.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api + +data class SyncConfig( + /** + * Time to keep sync connection alive for before making another request in milliseconds. + */ + val longPollTimeout: Long = 30_000L, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt index d3f6ec2287..1d6e79c8f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt @@ -68,6 +68,11 @@ sealed interface QueryStringValue { */ data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue + /** + * The tested field must not contain the [string]. + */ + data class NotContains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue + /** * Case enum for [ContentQueryStringValue]. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt index e701e0f3ba..234a8eee98 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt @@ -131,11 +131,10 @@ class SecretStoringUtils @Inject constructor( * * The secret is encrypted using the following method: AES/GCM/NoPadding */ - @SuppressLint("NewApi") @Throws(Exception::class) fun securelyStoreBytes(secret: ByteArray, keyAlias: String): ByteArray { return when { - buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> encryptBytesM(secret, keyAlias) + buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.M) -> encryptBytesM(secret, keyAlias) else -> encryptBytes(secret, keyAlias) } } @@ -156,10 +155,9 @@ class SecretStoringUtils @Inject constructor( } } - @SuppressLint("NewApi") fun securelyStoreObject(any: Any, keyAlias: String, output: OutputStream) { when { - buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> saveSecureObjectM(keyAlias, output, any) + buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.M) -> saveSecureObjectM(keyAlias, output, any) else -> saveSecureObject(keyAlias, output, any) } } @@ -189,7 +187,6 @@ class SecretStoringUtils @Inject constructor( return cipher } - @SuppressLint("NewApi") @RequiresApi(Build.VERSION_CODES.M) private fun getOrGenerateSymmetricKeyForAliasM(alias: String): SecretKey { val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt index a15e73eb88..96dac27618 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt @@ -32,5 +32,13 @@ fun Session.getRoomSummary(roomIdOrAlias: String): RoomSummary? = roomService(). /** * Get a user using the UserService of a Session. + * @param userId the userId to look for. + * @return a user with userId or null if the User is not known yet by the SDK. + * See [org.matrix.android.sdk.api.session.user.UserService.resolveUser] to ensure that a User is retrieved. */ fun Session.getUser(userId: String): User? = userService().getUser(userId) + +/** + * Similar to [getUser], but fallback to a User without details if the User is not known by the SDK, or if Session is null. + */ +fun Session?.getUserOrDefault(userId: String): User = this?.userService()?.getUser(userId) ?: User(userId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index a5e05f69e0..e0e662c789 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationServic import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.crypto.model.SessionInfo interface CryptoService { @@ -113,7 +114,19 @@ interface CryptoService { fun setRoomBlacklistUnverifiedDevices(roomId: String) - fun getDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? + fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? + + fun getCryptoDeviceInfo(deviceId: String, callback: MatrixCallback) + + fun getCryptoDeviceInfo(userId: String): List + + fun getLiveCryptoDeviceInfo(): LiveData> + + fun getLiveCryptoDeviceInfoWithId(deviceId: String): LiveData> + + fun getLiveCryptoDeviceInfo(userId: String): LiveData> + + fun getLiveCryptoDeviceInfo(userIds: List): LiveData> fun requestRoomKeyForEvent(event: Event) @@ -127,9 +140,9 @@ interface CryptoService { fun getMyDevicesInfo(): List - fun getLiveMyDevicesInfo(): LiveData> + fun getMyDevicesInfoLive(): LiveData> - fun getDeviceInfo(deviceId: String, callback: MatrixCallback) + fun getMyDevicesInfoLive(deviceId: String): LiveData> fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int @@ -156,14 +169,6 @@ interface CryptoService { fun downloadKeys(userIds: List, forceDownload: Boolean, callback: MatrixCallback>) - fun getCryptoDeviceInfo(userId: String): List - - fun getLiveCryptoDeviceInfo(): LiveData> - - fun getLiveCryptoDeviceInfo(userId: String): LiveData> - - fun getLiveCryptoDeviceInfo(userIds: List): LiveData> - fun addNewSessionListener(newSessionListener: NewSessionListener) fun removeSessionListener(listener: NewSessionListener) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index 5d2769ac3c..8031fcaeea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.members.MembershipService +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.relation.RelationService import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService @@ -60,11 +61,22 @@ interface Room { */ fun getRoomSummaryLive(): LiveData> + /** + * A live [LocalRoomSummary] associated with the room. + * You can observe this summary to get dynamic data from this room. + */ + fun getLocalRoomSummaryLive(): LiveData> + /** * A current snapshot of [RoomSummary] associated with the room. */ fun roomSummary(): RoomSummary? + /** + * A current snapshot of [LocalRoomSummary] associated with the room. + */ + fun localRoomSummary(): LocalRoomSummary? + /** * Use this room as a Space, if the type is correct. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index ad8106c9c1..65383f1007 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -117,6 +118,12 @@ interface RoomService { */ fun getRoomSummaryLive(roomId: String): LiveData> + /** + * A live [LocalRoomSummary] associated with the room with id [roomId]. + * You can observe this summary to get dynamic data from this room, even if the room is not joined yet + */ + fun getLocalRoomSummaryLive(roomId: String): LiveData> + /** * Get a snapshot list of room summaries. * @return the immutable list of [RoomSummary] diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt index 60963ef25a..d651f06e23 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt @@ -20,8 +20,10 @@ import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.RoomCategoryFilter import org.matrix.android.sdk.api.query.RoomTagQueryFilter import org.matrix.android.sdk.api.query.SpaceFilter +import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams.Builder import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomType +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams /** @@ -52,6 +54,10 @@ fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = * [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of this class. */ data class RoomSummaryQueryParams( + /** + * Query for the roomId. + */ + val roomId: QueryStringValue, /** * Query for the displayName of the room. The display name can be the value of the state event, * or a value returned by [org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider]. @@ -94,6 +100,7 @@ data class RoomSummaryQueryParams( * [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of [RoomSummaryQueryParams]. */ class Builder { + var roomId: QueryStringValue = QueryStringValue.NotContains(RoomLocalEcho.PREFIX) var displayName: QueryStringValue = QueryStringValue.NoCondition var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition var memberships: List = Membership.all() @@ -104,6 +111,7 @@ data class RoomSummaryQueryParams( var spaceFilter: SpaceFilter = SpaceFilter.NoFilter fun build() = RoomSummaryQueryParams( + roomId = roomId, displayName = displayName, canonicalAlias = canonicalAlias, memberships = memberships, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomCreationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomCreationState.kt new file mode 100644 index 0000000000..4fc99225c4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomCreationState.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.room.model + +enum class LocalRoomCreationState { + NOT_CREATED, + CREATING, + FAILURE, + CREATED +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomSummary.kt new file mode 100644 index 0000000000..eced1dd581 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/LocalRoomSummary.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.room.model + +import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams + +/** + * This class holds some data of a local room. + * It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService] + */ +data class LocalRoomSummary( + /** + * The roomId of the room. + */ + val roomId: String, + /** + * The room summary of the room. + */ + val roomSummary: RoomSummary?, + /** + * The creation params attached to the room. + */ + val createRoomParams: CreateRoomParams?, + /** + * The roomId of the created room (ie. created on the server), if any. + */ + val replacementRoomId: String?, + /** + * The creation state of the room. + */ + val creationState: LocalRoomCreationState, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/SpaceChildInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/SpaceChildInfo.kt index 7d3109fb6e..2388bee0ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/SpaceChildInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/SpaceChildInfo.kt @@ -34,5 +34,4 @@ data class SpaceChildInfo( val canonicalAlias: String?, val aliases: List?, val worldReadable: Boolean - ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt index 7ef0d63924..ec0e642ad3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/localecho/RoomLocalEcho.kt @@ -20,7 +20,7 @@ import java.util.UUID object RoomLocalEcho { - private const val PREFIX = "!local." + const val PREFIX = "!local." /** * Tell whether the provider room id is a local id. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceHierarchyData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceHierarchyData.kt index ecc3eb5224..d03f4c42cf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceHierarchyData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceHierarchyData.kt @@ -16,13 +16,13 @@ package org.matrix.android.sdk.api.session.space -import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo +import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent data class SpaceHierarchyData( val rootSummary: RoomSummary, val children: List, - val childrenState: List, + val childrenState: List, val nextToken: String? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt index c7a6405014..5d2a9412d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.api.session.space import android.net.Uri import androidx.lifecycle.LiveData -import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult typealias SpaceSummaryQueryParams = RoomSummaryQueryParams @@ -75,12 +75,12 @@ interface SpaceService { suggestedOnly: Boolean? = null, limit: Int? = null, from: String? = null, - knownStateList: List? = null + knownStateList: List? = null ): SpaceHierarchyData /** * Get a live list of space summaries. This list is refreshed as soon as the data changes. - * @return the [LiveData] of List[SpaceSummary] + * @return the [LiveData] of List[RoomSummary] */ fun getSpaceSummariesLive( queryParams: SpaceSummaryQueryParams, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildSummaryEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildSummaryEvent.kt new file mode 100644 index 0000000000..13aa0336e5 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildSummaryEvent.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.space.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.events.model.Content + +@JsonClass(generateAdapter = true) +data class SpaceChildSummaryEvent( + @Json(name = "type") val type: String? = null, + @Json(name = "state_key") val stateKey: String? = null, + @Json(name = "content") val content: Content? = null, + @Json(name = "sender") val senderId: String? = null, + @Json(name = "origin_server_ts") val originServerTs: Long? = null, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt index 0c5465e12a..7075023798 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt @@ -29,7 +29,7 @@ interface UserService { /** * Get a user from a userId. * @param userId the userId to look for. - * @return a user with userId or null + * @return a user with userId or null if the User is not known yet by the SDK. See [resolveUser] to ensure that a User is retrieved. */ fun getUser(userId: String): User? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt index 900a2e237f..c8c328c92c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.api.util +import androidx.annotation.ChecksSdkIntAtLeast + interface BuildVersionSdkIntProvider { /** * Return the current version of the Android SDK. @@ -26,9 +28,13 @@ interface BuildVersionSdkIntProvider { * Checks the if the current OS version is equal or greater than [version]. * @return A `non-null` result if true, `null` otherwise. */ + @ChecksSdkIntAtLeast(parameter = 0, lambda = 1) fun whenAtLeast(version: Int, result: () -> T): T? { return if (get() >= version) { result() } else null } + + @ChecksSdkIntAtLeast(parameter = 0) + fun isAtLeast(version: Int) = get() >= version } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 35c066dea8..8dd7c309c6 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -73,6 +73,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityConten import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.shouldShareHistory import org.matrix.android.sdk.api.session.sync.model.SyncResponse +import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting @@ -273,23 +274,18 @@ internal class DefaultCryptoService @Inject constructor( .executeBy(taskExecutor) } - override fun getLiveMyDevicesInfo(): LiveData> { + override fun getMyDevicesInfoLive(): LiveData> { return cryptoStore.getLiveMyDevicesInfo() } + override fun getMyDevicesInfoLive(deviceId: String): LiveData> { + return cryptoStore.getLiveMyDevicesInfo(deviceId) + } + override fun getMyDevicesInfo(): List { return cryptoStore.getMyDevicesInfo() } - override fun getDeviceInfo(deviceId: String, callback: MatrixCallback) { - getDeviceInfoTask - .configureWith(GetDeviceInfoTask.Params(deviceId)) { - this.executionThread = TaskThread.CRYPTO - this.callback = callback - } - .executeBy(taskExecutor) - } - override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int { return cryptoStore.inboundGroupSessionsCount(onlyBackedUp) } @@ -513,7 +509,7 @@ internal class DefaultCryptoService @Inject constructor( * @param userId the user id * @param deviceId the device id */ - override fun getDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? { + override fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? { return if (userId.isNotEmpty() && !deviceId.isNullOrEmpty()) { cryptoStore.getUserDevice(userId, deviceId) } else { @@ -521,6 +517,15 @@ internal class DefaultCryptoService @Inject constructor( } } + override fun getCryptoDeviceInfo(deviceId: String, callback: MatrixCallback) { + getDeviceInfoTask + .configureWith(GetDeviceInfoTask.Params(deviceId)) { + this.executionThread = TaskThread.CRYPTO + this.callback = callback + } + .executeBy(taskExecutor) + } + override fun getCryptoDeviceInfo(userId: String): List { return cryptoStore.getUserDeviceList(userId).orEmpty() } @@ -529,6 +534,10 @@ internal class DefaultCryptoService @Inject constructor( return cryptoStore.getLiveDeviceList() } + override fun getLiveCryptoDeviceInfoWithId(deviceId: String): LiveData> { + return cryptoStore.getLiveDeviceWithId(deviceId) + } + override fun getLiveCryptoDeviceInfo(userId: String): LiveData> { return cryptoStore.getLiveDeviceList(userId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt index 0413fc730c..56eba25249 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt @@ -238,10 +238,14 @@ internal interface IMXCryptoStore { // TODO temp fun getLiveDeviceList(): LiveData> + fun getLiveDeviceWithId(deviceId: String): LiveData> + fun getMyDevicesInfo(): List fun getLiveMyDevicesInfo(): LiveData> + fun getLiveMyDevicesInfo(deviceId: String): LiveData> + fun saveMyDevicesInfo(info: List) /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index f5468634cb..3b8fa4cacd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -55,6 +55,7 @@ import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper +import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailMapper @@ -68,6 +69,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity +import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntity @@ -112,6 +114,7 @@ internal class RealmCryptoStore @Inject constructor( @UserId private val userId: String, @DeviceId private val deviceId: String?, private val clock: Clock, + private val myDeviceLastSeenInfoEntityMapper: MyDeviceLastSeenInfoEntityMapper, ) : IMXCryptoStore { /* ========================================================================================== @@ -578,6 +581,12 @@ internal class RealmCryptoStore @Inject constructor( } } + override fun getLiveDeviceWithId(deviceId: String): LiveData> { + return Transformations.map(getLiveDeviceList()) { devices -> + devices.firstOrNull { it.deviceId == deviceId }.toOptional() + } + } + override fun getMyDevicesInfo(): List { return monarchy.fetchAllCopiedSync { it.where() @@ -596,17 +605,24 @@ internal class RealmCryptoStore @Inject constructor( { realm: Realm -> realm.where() }, - { entity -> - DeviceInfo( - deviceId = entity.deviceId, - lastSeenIp = entity.lastSeenIp, - lastSeenTs = entity.lastSeenTs, - displayName = entity.displayName - ) - } + { entity -> myDeviceLastSeenInfoEntityMapper.map(entity) } ) } + override fun getLiveMyDevicesInfo(deviceId: String): LiveData> { + val liveData = monarchy.findAllMappedWithChanges( + { realm: Realm -> + realm.where() + .equalTo(MyDeviceLastSeenInfoEntityFields.DEVICE_ID, deviceId) + }, + { entity -> myDeviceLastSeenInfoEntityMapper.map(entity) } + ) + + return Transformations.map(liveData) { + it.firstOrNull().toOptional() + } + } + override fun saveMyDevicesInfo(info: List) { val entities = info.map { MyDeviceLastSeenInfoEntity( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapper.kt new file mode 100644 index 0000000000..38a7569aab --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapper.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.crypto.store.db.mapper + +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity +import javax.inject.Inject + +internal class MyDeviceLastSeenInfoEntityMapper @Inject constructor() { + + fun map(entity: MyDeviceLastSeenInfoEntity): DeviceInfo { + return DeviceInfo( + deviceId = entity.deviceId, + lastSeenIp = entity.lastSeenIp, + lastSeenTs = entity.lastSeenTs, + displayName = entity.displayName + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 0b11863864..2693ca474c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -53,6 +53,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo033 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo034 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo035 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo036 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo037 import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import javax.inject.Inject @@ -61,7 +62,7 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : MatrixRealmMigration( dbName = "Session", - schemaVersion = 36L, + schemaVersion = 37L, ) { /** * Forces all RealmSessionStoreMigration instances to be equal. @@ -107,5 +108,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 34) MigrateSessionTo034(realm).perform() if (oldVersion < 35) MigrateSessionTo035(realm).perform() if (oldVersion < 36) MigrateSessionTo036(realm).perform() + if (oldVersion < 37) MigrateSessionTo037(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LocalRoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LocalRoomSummaryMapper.kt new file mode 100644 index 0000000000..09cb5985f3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LocalRoomSummaryMapper.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.database.mapper + +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary +import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity +import javax.inject.Inject + +internal class LocalRoomSummaryMapper @Inject constructor( + private val roomSummaryMapper: RoomSummaryMapper, +) { + + fun map(localRoomSummaryEntity: LocalRoomSummaryEntity): LocalRoomSummary { + return LocalRoomSummary( + roomId = localRoomSummaryEntity.roomId, + roomSummary = localRoomSummaryEntity.roomSummaryEntity?.let { roomSummaryMapper.map(it) }, + createRoomParams = localRoomSummaryEntity.createRoomParams, + replacementRoomId = localRoomSummaryEntity.replacementRoomId, + creationState = localRoomSummaryEntity.creationState + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo037.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo037.kt new file mode 100644 index 0000000000..cdb0b6c682 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo037.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState +import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +internal class MigrateSessionTo037(realm: DynamicRealm) : RealmMigrator(realm, 37) { + + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("LocalRoomSummaryEntity") + ?.addField(LocalRoomSummaryEntityFields.REPLACEMENT_ROOM_ID, String::class.java) + ?.addField(LocalRoomSummaryEntityFields.STATE_STR, String::class.java) + ?.transform { obj -> + obj.set(LocalRoomSummaryEntityFields.STATE_STR, LocalRoomCreationState.NOT_CREATED.name) + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt index fd8331e986..a978e3719d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt @@ -18,15 +18,24 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmObject import io.realm.annotations.PrimaryKey +import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.create.toJSONString internal open class LocalRoomSummaryEntity( @PrimaryKey var roomId: String = "", var roomSummaryEntity: RoomSummaryEntity? = null, - private var createRoomParamsStr: String? = null + var replacementRoomId: String? = null, ) : RealmObject() { + private var stateStr: String = LocalRoomCreationState.NOT_CREATED.name + var creationState: LocalRoomCreationState + get() = LocalRoomCreationState.valueOf(stateStr) + set(value) { + stateStr = value.name + } + + private var createRoomParamsStr: String? = null var createRoomParams: CreateRoomParams? get() { return CreateRoomParams.fromJson(createRoomParamsStr) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt index 527350bedc..44730eb75d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt @@ -22,10 +22,6 @@ import io.realm.kotlin.where import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields -internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String? = null): RealmQuery { - val query = realm.where() - if (roomId != null) { - query.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId) - } - return query +internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String): RealmQuery { + return realm.where().equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadReceiptEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadReceiptEntityQueries.kt index b180c06e2c..170814d3f2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadReceiptEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadReceiptEntityQueries.kt @@ -33,6 +33,11 @@ internal fun ReadReceiptEntity.Companion.whereUserId(realm: Realm, userId: Strin .equalTo(ReadReceiptEntityFields.USER_ID, userId) } +internal fun ReadReceiptEntity.Companion.whereRoomId(realm: Realm, roomId: String): RealmQuery { + return realm.where() + .equalTo(ReadReceiptEntityFields.ROOM_ID, roomId) +} + internal fun ReadReceiptEntity.Companion.createUnmanaged(roomId: String, eventId: String, userId: String, originServerTs: Double): ReadReceiptEntity { return ReadReceiptEntity().apply { this.primaryKey = "${roomId}_$userId" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt index b2ab9879df..a93ff42c9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt @@ -38,6 +38,7 @@ internal class QueryStringValueProcessor @Inject constructor( is ContentQueryStringValue -> when (queryStringValue) { is QueryStringValue.Equals -> equalTo(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase()) is QueryStringValue.Contains -> contains(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase()) + is QueryStringValue.NotContains -> not().process(field, QueryStringValue.Contains(queryStringValue.string, queryStringValue.case)) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt index abea2d34cd..262c111b73 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt @@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.members.MembershipService +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.model.relation.RelationService @@ -82,6 +83,14 @@ internal class DefaultRoom( return roomSummaryDataSource.getRoomSummary(roomId) } + override fun getLocalRoomSummaryLive(): LiveData> { + return roomSummaryDataSource.getLocalRoomSummaryLive(roomId) + } + + override fun localRoomSummary(): LocalRoomSummary? { + return roomSummaryDataSource.getLocalRoomSummary(roomId) + } + override fun asSpace(): Space? { if (roomSummary()?.roomType != RoomType.SPACE) return null return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index 989bcaee44..6d72b8ef20 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -29,10 +29,12 @@ import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams +import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.session.room.peeking.PeekResult import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount @@ -106,6 +108,10 @@ internal class DefaultRoomService @Inject constructor( return roomSummaryDataSource.getRoomSummaryLive(roomId) } + override fun getLocalRoomSummaryLive(roomId: String): LiveData> { + return roomSummaryDataSource.getLocalRoomSummaryLive(roomId) + } + override fun getRoomSummaries( queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder @@ -173,7 +179,10 @@ internal class DefaultRoomService @Inject constructor( } override suspend fun onRoomDisplayed(roomId: String) { - updateBreadcrumbsTask.execute(UpdateBreadcrumbsTask.Params(roomId)) + // Do not add local rooms to the recent rooms list as they should not be known by the server + if (!RoomLocalEcho.isLocalEchoId(roomId)) { + updateBreadcrumbsTask.execute(UpdateBreadcrumbsTask.Params(roomId)) + } } override suspend fun joinRoom(roomIdOrAlias: String, reason: String?, viaServers: List) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt index 02538a5cc3..2245eb8513 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt @@ -17,38 +17,23 @@ package org.matrix.android.sdk.internal.session.room.create import com.zhuinden.monarchy.Monarchy -import io.realm.kotlin.where import kotlinx.coroutines.TimeoutCancellationException -import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.query.QueryStringValue -import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.api.session.events.model.toContent -import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure +import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState +import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams -import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent -import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.internal.database.awaitNotEmptyResult -import org.matrix.android.sdk.internal.database.mapper.toEntity -import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.database.model.EventEntityFields -import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity -import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields -import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore -import org.matrix.android.sdk.internal.database.query.getOrCreate +import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.whereRoomId import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.di.UserId -import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource +import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.task.Task -import org.matrix.android.sdk.internal.util.awaitTransaction -import org.matrix.android.sdk.internal.util.time.Clock -import java.util.UUID import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -56,94 +41,100 @@ import javax.inject.Inject * Create a room on the server from a local room. * The configuration of the local room will be use to configure the new room. * The potential local room members will also be invited to this new room. - * - * A local tombstone event will be created to indicate that the local room has been replacing by the new one. */ internal interface CreateRoomFromLocalRoomTask : Task { data class Params(val localRoomId: String) } internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor( - @UserId private val userId: String, @SessionDatabase private val monarchy: Monarchy, private val createRoomTask: CreateRoomTask, - private val stateEventDataSource: StateEventDataSource, - private val clock: Clock, + private val roomSummaryDataSource: RoomSummaryDataSource, ) : CreateRoomFromLocalRoomTask { private val realmConfiguration get() = monarchy.realmConfiguration override suspend fun execute(params: CreateRoomFromLocalRoomTask.Params): String { - val replacementRoomId = stateEventDataSource.getStateEvent(params.localRoomId, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty) - ?.content.toModel() - ?.replacementRoomId + val localRoomSummary = roomSummaryDataSource.getLocalRoomSummary(params.localRoomId) + ?: error("## CreateRoomFromLocalRoomTask - Cannot retrieve LocalRoomSummary with roomId ${params.localRoomId}") - if (replacementRoomId != null) { - return replacementRoomId + // If a room has already been created for the given local room, return the existing roomId + if (localRoomSummary.replacementRoomId != null) { + return localRoomSummary.replacementRoomId } - var createRoomParams: CreateRoomParams? = null - var isEncrypted = false - monarchy.doWithRealm { realm -> - realm.where() - .equalTo(LocalRoomSummaryEntityFields.ROOM_ID, params.localRoomId) - .findFirst() - ?.let { - createRoomParams = it.createRoomParams - isEncrypted = it.roomSummaryEntity?.isEncrypted.orFalse() - } + if (localRoomSummary.createRoomParams != null && localRoomSummary.roomSummary != null) { + return createRoom(params.localRoomId, localRoomSummary.roomSummary, localRoomSummary.createRoomParams) + } else { + error("## CreateRoomFromLocalRoomTask - Invalid LocalRoomSummary: $localRoomSummary") } - val roomId = createRoomTask.execute(createRoomParams!!) + } + /** + * Create a room on the server for the given local room. + * + * @param localRoomId the local room identifier. + * @param localRoomSummary the RoomSummary of the local room. + * @param createRoomParams the CreateRoomParams object which was used to configure the local room. + * + * @return the identifier of the created room. + */ + private suspend fun createRoom(localRoomId: String, localRoomSummary: RoomSummary, createRoomParams: CreateRoomParams): String { + updateCreationState(localRoomId, LocalRoomCreationState.CREATING) + val replacementRoomId = runCatching { + createRoomTask.execute(createRoomParams) + }.fold( + { it }, + { + updateCreationState(localRoomId, LocalRoomCreationState.FAILURE) + throw it + } + ) + updateReplacementRoomId(localRoomId, replacementRoomId) + waitForRoomEvents(replacementRoomId, localRoomSummary) + updateCreationState(localRoomId, LocalRoomCreationState.CREATED) + return replacementRoomId + } + + /** + * Wait for all the room events before triggering the created state. + * + * @param replacementRoomId the identifier of the created room + * @param localRoomSummary the RoomSummary of the local room. + */ + private suspend fun waitForRoomEvents(replacementRoomId: String, localRoomSummary: RoomSummary) { try { - // Wait for all the room events before triggering the replacement room awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> realm.where(RoomSummaryEntity::class.java) - .equalTo(RoomSummaryEntityFields.ROOM_ID, roomId) - .equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, createRoomParams?.invitedUserIds?.size ?: 0) + .equalTo(RoomSummaryEntityFields.ROOM_ID, replacementRoomId) + .equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, localRoomSummary.invitedMembersCount) } awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> - EventEntity.whereRoomId(realm, roomId) + EventEntity.whereRoomId(realm, replacementRoomId) .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY) } - if (isEncrypted) { + if (localRoomSummary.isEncrypted) { awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> - EventEntity.whereRoomId(realm, roomId) + EventEntity.whereRoomId(realm, replacementRoomId) .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION) } } } catch (exception: TimeoutCancellationException) { - throw CreateRoomFailure.CreatedWithTimeout(roomId) + updateCreationState(localRoomSummary.roomId, LocalRoomCreationState.FAILURE) + throw CreateRoomFailure.CreatedWithTimeout(replacementRoomId) } - - createTombstoneEvent(params, roomId) - return roomId } - /** - * Create a Tombstone event to indicate that the local room has been replaced by a new one. - */ - private suspend fun createTombstoneEvent(params: CreateRoomFromLocalRoomTask.Params, roomId: String) { - val now = clock.epochMillis() - val event = Event( - type = EventType.STATE_ROOM_TOMBSTONE, - senderId = userId, - originServerTs = now, - stateKey = "", - eventId = UUID.randomUUID().toString(), - content = RoomTombstoneContent( - replacementRoomId = roomId - ).toContent() - ) - monarchy.awaitTransaction { realm -> - val eventEntity = event.toEntity(params.localRoomId, SendState.SYNCED, now).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC) - if (event.stateKey != null && event.type != null && event.eventId != null) { - CurrentStateEventEntity.getOrCreate(realm, params.localRoomId, event.stateKey, event.type).apply { - eventId = event.eventId - root = eventEntity - } - } + private fun updateCreationState(roomId: String, creationState: LocalRoomCreationState) { + monarchy.runTransactionSync { realm -> + LocalRoomSummaryEntity.where(realm, roomId).findFirst()?.creationState = creationState + } + } + + private fun updateReplacementRoomId(localRoomId: String, replacementRoomId: String) { + monarchy.runTransactionSync { realm -> + LocalRoomSummaryEntity.where(realm, localRoomId).findFirst()?.replacementRoomId = replacementRoomId } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt index 49951d2da0..a60c7e6a27 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/delete/DeleteLocalRoomTask.kt @@ -22,12 +22,15 @@ import org.matrix.android.sdk.internal.database.model.ChunkEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity +import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity +import org.matrix.android.sdk.internal.database.model.ReadReceiptsSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.deleteOnCascade import org.matrix.android.sdk.internal.database.query.where +import org.matrix.android.sdk.internal.database.query.whereInRoom import org.matrix.android.sdk.internal.database.query.whereRoomId import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask.Params @@ -50,6 +53,12 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor( if (RoomLocalEcho.isLocalEchoId(roomId)) { monarchy.awaitTransaction { realm -> Timber.i("## DeleteLocalRoomTask - delete local room id $roomId") + ReadReceiptsSummaryEntity.whereInRoom(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - ReadReceiptsSummaryEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() + ReadReceiptEntity.whereRoomId(realm, roomId = roomId).findAll() + ?.also { Timber.i("## DeleteLocalRoomTask - ReadReceiptEntity - delete ${it.size} entries") } + ?.deleteAllFromRealm() RoomMemberSummaryEntity.where(realm, roomId = roomId).findAll() ?.also { Timber.i("## DeleteLocalRoomTask - RoomMemberSummaryEntity - delete ${it.size} entries") } ?.deleteAllFromRealm() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt deleted file mode 100644 index 55363a7251..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2020 The Matrix.org Foundation C.I.C. - * - * 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 org.matrix.android.sdk.internal.session.room.send.queue - -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import org.matrix.android.sdk.api.auth.data.SessionParams -import org.matrix.android.sdk.api.auth.data.sessionId -import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.failure.Failure -import org.matrix.android.sdk.api.failure.isLimitExceededError -import org.matrix.android.sdk.api.failure.isTokenError -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.crypto.CryptoService -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.sync.SyncState -import org.matrix.android.sdk.api.util.Cancelable -import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.task.TaskExecutor -import timber.log.Timber -import java.io.IOException -import java.util.Timer -import java.util.TimerTask -import java.util.concurrent.LinkedBlockingQueue -import javax.inject.Inject -import kotlin.concurrent.schedule - -/** - * A simple ever running thread unique for that session responsible of sending events in order. - * Each send is retried 3 times, if there is no network (e.g if cannot ping homeserver) it will wait and - * periodically test reachability before resume (does not count as a retry) - * - * If the app is killed before all event were sent, on next wakeup the scheduled events will be re posted - */ -@Deprecated("You should know use EventSenderProcessorCoroutine instead") -@SessionScope -internal class EventSenderProcessorThread @Inject constructor( - private val cryptoService: CryptoService, - private val sessionParams: SessionParams, - private val queuedTaskFactory: QueuedTaskFactory, - private val taskExecutor: TaskExecutor, - private val memento: QueueMemento -) : Thread("Matrix-SENDER_THREAD_SID_${sessionParams.credentials.sessionId()}"), EventSenderProcessor { - - private fun markAsManaged(task: QueuedTask) { - memento.track(task) - } - - private fun markAsFinished(task: QueuedTask) { - memento.unTrack(task) - } - - override fun onSessionStarted(session: Session) { - start() - } - - override fun onSessionStopped(session: Session) { - interrupt() - } - - override fun start() { - super.start() - // We should check for sending events not handled because app was killed - // But we should be careful of only took those that was submitted to us, because if it's - // for example it's a media event it is handled by some worker and he will handle it - // This is a bit fragile :/ - // also some events cannot be retried manually by users, e.g reactions - // they were previously relying on workers to do the work :/ and was expected to always finally succeed - // Also some echos are not to be resent like redaction echos (fake event created for aggregation) - - tryOrNull { - taskExecutor.executorScope.launch { - Timber.d("## Send relaunched pending events on restart") - memento.restoreTasks(this@EventSenderProcessorThread) - } - } - } - - // API - override fun postEvent(event: Event): Cancelable { - return postEvent(event, event.roomId?.let { cryptoService.isRoomEncrypted(it) } ?: false) - } - - override fun postEvent(event: Event, encrypt: Boolean): Cancelable { - val task = queuedTaskFactory.createSendTask(event, encrypt) - return postTask(task) - } - - override fun postRedaction(redactionLocalEcho: Event, reason: String?): Cancelable { - return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason) - } - - override fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?): Cancelable { - val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason) - return postTask(task) - } - - override fun postTask(task: QueuedTask): Cancelable { - // non blocking add to queue - sendingQueue.add(task) - markAsManaged(task) - return task - } - - override fun cancel(eventId: String, roomId: String) { - (currentTask as? SendEventQueuedTask) - ?.takeIf { it.event.eventId == eventId && it.event.roomId == roomId } - ?.cancel() - } - - companion object { - private const val RETRY_WAIT_TIME_MS = 10_000L - } - - private var currentTask: QueuedTask? = null - - private var sendingQueue = LinkedBlockingQueue() - - private var networkAvailableLock = Object() - private var canReachServer = true - private var retryNoNetworkTask: TimerTask? = null - - override fun run() { - Timber.v("## SendThread started") - try { - while (!isInterrupted) { - Timber.v("## SendThread wait for task to process") - val task = sendingQueue.take() - .also { currentTask = it } - Timber.v("## SendThread Found task to process $task") - - if (task.isCancelled()) { - Timber.v("## SendThread send cancelled for $task") - // we do not execute this one - continue - } - // we check for network connectivity - while (!canReachServer) { - Timber.v("## SendThread cannot reach server") - // schedule to retry - waitForNetwork() - // if thread as been killed meanwhile -// if (state == State.KILLING) break - } - Timber.v("## Server is Reachable") - // so network is available - - runBlocking { - retryLoop@ while (task.retryCount.get() < 3) { - try { - // SendPerformanceProfiler.startStage(task.event.eventId!!, SendPerformanceProfiler.Stages.SEND_WORKER) - Timber.v("## SendThread retryLoop for $task retryCount ${task.retryCount}") - task.execute() - // sendEventTask.execute(SendEventTask.Params(task.event, task.encrypt, cryptoService)) - // SendPerformanceProfiler.stopStage(task.event.eventId, SendPerformanceProfiler.Stages.SEND_WORKER) - break@retryLoop - } catch (exception: Throwable) { - when { - exception is IOException || exception is Failure.NetworkConnection -> { - canReachServer = false - if (task.retryCount.getAndIncrement() >= 3) task.onTaskFailed() - while (!canReachServer) { - Timber.v("## SendThread retryLoop cannot reach server") - // schedule to retry - waitForNetwork() - } - } - (exception.isLimitExceededError()) -> { - if (task.retryCount.getAndIncrement() >= 3) task.onTaskFailed() - Timber.v("## SendThread retryLoop retryable error for $task reason: ${exception.localizedMessage}") - // wait a bit - // Todo if its a quota exception can we get timout? - sleep(3_000) - continue@retryLoop - } - exception.isTokenError() -> { - Timber.v("## SendThread retryLoop retryable TOKEN error, interrupt") - // we can exit the loop - task.onTaskFailed() - throw InterruptedException() - } - exception is CancellationException -> { - Timber.v("## SendThread task has been cancelled") - break@retryLoop - } - else -> { - Timber.v("## SendThread retryLoop Un-Retryable error, try next task") - // this task is in error, check next one? - task.onTaskFailed() - break@retryLoop - } - } - } - } - } - markAsFinished(task) - } - } catch (interruptionException: InterruptedException) { - // will be thrown is thread is interrupted while seeping - interrupt() - Timber.v("## InterruptedException!! ${interruptionException.localizedMessage}") - } -// state = State.KILLED - // is this needed? - retryNoNetworkTask?.cancel() - Timber.w("## SendThread finished") - } - - private fun waitForNetwork() { - retryNoNetworkTask = Timer(SyncState.NoNetwork.toString(), false).schedule(RETRY_WAIT_TIME_MS) { - synchronized(networkAvailableLock) { - canReachServer = HomeServerAvailabilityChecker(sessionParams).check().also { - Timber.v("## SendThread checkHostAvailable $it") - } - networkAvailableLock.notify() - } - } - synchronized(networkAvailableLock) { networkAvailableLock.wait() } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index 82fc94df7c..5c4ed8012b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.room.ResultBoundaries import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType @@ -43,7 +44,9 @@ import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotification import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional +import org.matrix.android.sdk.internal.database.mapper.LocalRoomSummaryMapper import org.matrix.android.sdk.internal.database.mapper.RoomSummaryMapper +import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.findByAlias @@ -57,6 +60,7 @@ import javax.inject.Inject internal class RoomSummaryDataSource @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val roomSummaryMapper: RoomSummaryMapper, + private val localRoomSummaryMapper: LocalRoomSummaryMapper, private val queryStringValueProcessor: QueryStringValueProcessor, ) { @@ -95,6 +99,25 @@ internal class RoomSummaryDataSource @Inject constructor( ) } + fun getLocalRoomSummary(roomId: String): LocalRoomSummary? { + return monarchy + .fetchCopyMap({ + LocalRoomSummaryEntity.where(it, roomId).findFirst() + }, { entity, _ -> + localRoomSummaryMapper.map(entity) + }) + } + + fun getLocalRoomSummaryLive(roomId: String): LiveData> { + val liveData = monarchy.findAllMappedWithChanges( + { realm -> LocalRoomSummaryEntity.where(realm, roomId) }, + { localRoomSummaryMapper.map(it) } + ) + return Transformations.map(liveData) { results -> + results.firstOrNull().toOptional() + } + } + fun getRoomSummariesLive( queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE @@ -272,6 +295,7 @@ internal class RoomSummaryDataSource @Inject constructor( val query = with(queryStringValueProcessor) { RoomSummaryEntity.where(realm) .process(RoomSummaryEntityFields.ROOM_ID, QueryStringValue.IsNotEmpty) + .process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId) .process(queryParams.displayName.toDisplayNameField(), queryParams.displayName) .process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias) .process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt index d2f1b3202b..cd13b03017 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt @@ -21,7 +21,6 @@ import androidx.lifecycle.LiveData import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.query.QueryStringValue -import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel @@ -45,6 +44,7 @@ import org.matrix.android.sdk.api.session.space.SpaceHierarchyData import org.matrix.android.sdk.api.session.space.SpaceService import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams import org.matrix.android.sdk.api.session.space.model.SpaceChildContent +import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent import org.matrix.android.sdk.api.session.space.model.SpaceParentContent import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult import org.matrix.android.sdk.internal.di.UserId @@ -128,7 +128,7 @@ internal class DefaultSpaceService @Inject constructor( suggestedOnly: Boolean?, limit: Int?, from: String?, - knownStateList: List? + knownStateList: List? ): SpaceHierarchyData { val spacesResponse = getSpacesResponse(spaceId, suggestedOnly, limit, from) val spaceRootResponse = spacesResponse.getRoot(spaceId) @@ -180,7 +180,7 @@ internal class DefaultSpaceService @Inject constructor( private fun List?.mapSpaceChildren( spaceId: String, spaceRootResponse: SpaceChildSummaryResponse?, - knownStateList: List?, + knownStateList: List?, ) = this?.filterIdIsNot(spaceId) ?.toSpaceChildInfoList(spaceId, spaceRootResponse, knownStateList) .orEmpty() @@ -190,7 +190,7 @@ internal class DefaultSpaceService @Inject constructor( private fun List.toSpaceChildInfoList( spaceId: String, rootRoomResponse: SpaceChildSummaryResponse?, - knownStateList: List?, + knownStateList: List?, ) = flatMap { spaceChildSummary -> (rootRoomResponse?.childrenState ?: knownStateList) ?.filter { it.isChildOf(spaceChildSummary) } @@ -198,10 +198,14 @@ internal class DefaultSpaceService @Inject constructor( .orEmpty() } - private fun Event.isChildOf(space: SpaceChildSummaryResponse) = stateKey == space.roomId && type == EventType.STATE_SPACE_CHILD + private fun SpaceChildSummaryEvent.isChildOf(space: SpaceChildSummaryResponse): Boolean { + return stateKey == space.roomId && type == EventType.STATE_SPACE_CHILD + } - private fun Event.toSpaceChildInfo(spaceId: String, summary: SpaceChildSummaryResponse) = content.toModel()?.let { content -> - createSpaceChildInfo(spaceId, summary, content) + private fun SpaceChildSummaryEvent.toSpaceChildInfo(spaceId: String, summary: SpaceChildSummaryResponse): SpaceChildInfo? { + return content.toModel()?.let { content -> + createSpaceChildInfo(spaceId, summary, content) + } } private fun createSpaceChildInfo( @@ -255,7 +259,7 @@ internal class DefaultSpaceService @Inject constructor( stateKey = QueryStringValue.IsEmpty ) val powerLevelsContent = powerLevelsEvent?.content?.toModel() - ?: throw UnsupportedOperationException("Cannot add canonical child, missing powerlevel") + ?: throw UnsupportedOperationException("Cannot add canonical child, missing power level") val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent) if (!powerLevelsHelper.isUserAllowedToSend(userId, true, EventType.STATE_SPACE_CHILD)) { throw UnsupportedOperationException("Cannot add canonical child, not enough power level") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt index e3f8977ac5..0419c5acf1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.space import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent /** * The fields are the same as those returned by /publicRooms (see spec), with the addition of: @@ -36,10 +36,11 @@ internal data class SpaceChildSummaryResponse( */ @Json(name = "room_type") val roomType: String? = null, - /** The m.space.child events of the room. For each event, only the following fields are included: - * type, state_key, content, room_id, sender, with the addition of origin_server_ts. + /** + * The m.space.child events of the room. For each event, only the following fields are included: + * type, state_key, content, sender, and of origin_server_ts. */ - @Json(name = "children_state") val childrenState: List? = null, + @Json(name = "children_state") val childrenState: List? = null, /** * Aliases of the room. May be empty. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt index b47b215655..d3f2a3f044 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.isTokenError @@ -52,7 +53,6 @@ import javax.inject.Inject import kotlin.concurrent.schedule private const val RETRY_WAIT_TIME_MS = 10_000L -private const val DEFAULT_LONG_POOL_TIMEOUT = 30_000L private val loggerTag = LoggerTag("SyncThread", LoggerTag.SYNC) @@ -61,7 +61,8 @@ internal class SyncThread @Inject constructor( private val networkConnectivityChecker: NetworkConnectivityChecker, private val backgroundDetectionObserver: BackgroundDetectionObserver, private val activeCallHandler: ActiveCallHandler, - private val lightweightSettingsStorage: DefaultLightweightSettingsStorage + private val lightweightSettingsStorage: DefaultLightweightSettingsStorage, + private val matrixConfiguration: MatrixConfiguration, ) : Thread("Matrix-SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener { private var state: SyncState = SyncState.Idle @@ -181,7 +182,7 @@ internal class SyncThread @Inject constructor( val timeout = when { previousSyncResponseHasToDevice -> 0L /* Force timeout to 0 */ afterPause -> 0L /* No timeout after a pause */ - else -> DEFAULT_LONG_POOL_TIMEOUT + else -> matrixConfiguration.syncConfig.longPollTimeout } Timber.tag(loggerTag.value).d("Execute sync request with timeout $timeout") val presence = lightweightSettingsStorage.getSyncPresenceStatus() diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapperTest.kt new file mode 100644 index 0000000000..a27f430edc --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapperTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.crypto.store.db.mapper + +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity + +private const val A_DEVICE_ID = "device-id" +private const val AN_IP_ADDRESS = "ip-address" +private const val A_TIMESTAMP = 123L +private const val A_DISPLAY_NAME = "display-name" + +class MyDeviceLastSeenInfoEntityMapperTest { + + private val myDeviceLastSeenInfoEntityMapper = MyDeviceLastSeenInfoEntityMapper() + + @Test + fun `given an entity when mapping to model then all fields are correctly mapped`() { + val entity = MyDeviceLastSeenInfoEntity( + deviceId = A_DEVICE_ID, + lastSeenIp = AN_IP_ADDRESS, + lastSeenTs = A_TIMESTAMP, + displayName = A_DISPLAY_NAME + ) + val expectedDeviceInfo = DeviceInfo( + deviceId = A_DEVICE_ID, + lastSeenIp = AN_IP_ADDRESS, + lastSeenTs = A_TIMESTAMP, + displayName = A_DISPLAY_NAME + ) + + val deviceInfo = myDeviceLastSeenInfoEntityMapper.map(entity) + + deviceInfo shouldBeEqualTo expectedDeviceInfo + } +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/create/DefaultCreateRoomFromLocalRoomTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/create/DefaultCreateRoomFromLocalRoomTaskTest.kt index d3732363b5..9e34280437 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/create/DefaultCreateRoomFromLocalRoomTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/create/DefaultCreateRoomFromLocalRoomTaskTest.kt @@ -22,21 +22,22 @@ import io.mockk.coVerify import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic +import io.mockk.spyk import io.mockk.unmockkAll +import io.mockk.verify +import io.mockk.verifyOrder import io.realm.kotlin.where import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldBeNull import org.junit.After import org.junit.Before import org.junit.Test -import org.matrix.android.sdk.api.query.QueryStringValue -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.api.session.events.model.toContent -import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams -import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent import org.matrix.android.sdk.internal.database.awaitNotEmptyResult import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventEntity @@ -44,29 +45,24 @@ import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.getOrCreate -import org.matrix.android.sdk.internal.util.time.DefaultClock import org.matrix.android.sdk.test.fakes.FakeMonarchy -import org.matrix.android.sdk.test.fakes.FakeStateEventDataSource +import org.matrix.android.sdk.test.fakes.FakeRoomSummaryDataSource private const val A_LOCAL_ROOM_ID = "local.a-local-room-id" private const val AN_EXISTING_ROOM_ID = "an-existing-room-id" private const val A_ROOM_ID = "a-room-id" -private const val MY_USER_ID = "my-user-id" @ExperimentalCoroutinesApi internal class DefaultCreateRoomFromLocalRoomTaskTest { private val fakeMonarchy = FakeMonarchy() - private val clock = DefaultClock() private val createRoomTask = mockk() - private val fakeStateEventDataSource = FakeStateEventDataSource() + private val fakeRoomSummaryDataSource = FakeRoomSummaryDataSource() private val defaultCreateRoomFromLocalRoomTask = DefaultCreateRoomFromLocalRoomTask( - userId = MY_USER_ID, monarchy = fakeMonarchy.instance, createRoomTask = createRoomTask, - stateEventDataSource = fakeStateEventDataSource.instance, - clock = clock + roomSummaryDataSource = fakeRoomSummaryDataSource.instance, ) @Before @@ -91,13 +87,12 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest { @Test fun `given a local room id when execute then the existing room id is kept`() = runTest { // Given - givenATombstoneEvent( - Event( - roomId = A_LOCAL_ROOM_ID, - type = EventType.STATE_ROOM_TOMBSTONE, - stateKey = "", - content = RoomTombstoneContent(replacementRoomId = AN_EXISTING_ROOM_ID).toContent() - ) + val aCreateRoomParams = mockk(relaxed = true) + givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aCreationState = LocalRoomCreationState.CREATED, aReplacementRoomId = AN_EXISTING_ROOM_ID) + val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity( + aCreateRoomParams = aCreateRoomParams, + aCreationState = LocalRoomCreationState.CREATED, + aReplacementRoomId = AN_EXISTING_ROOM_ID ) // When @@ -105,20 +100,18 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest { val result = defaultCreateRoomFromLocalRoomTask.execute(params) // Then - verifyTombstoneEvent(AN_EXISTING_ROOM_ID) + fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID) result shouldBeEqualTo AN_EXISTING_ROOM_ID + aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo AN_EXISTING_ROOM_ID + aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED } @Test fun `given a local room id when execute then it is correctly executed`() = runTest { // Given - val aCreateRoomParams = mockk() - val aLocalRoomSummaryEntity = mockk { - every { roomSummaryEntity } returns mockk(relaxed = true) - every { createRoomParams } returns aCreateRoomParams - } - givenATombstoneEvent(null) - givenALocalRoomSummaryEntity(aLocalRoomSummaryEntity) + val aCreateRoomParams = mockk(relaxed = true) + givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null) + val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null) coEvery { createRoomTask.execute(any()) } returns A_ROOM_ID @@ -127,32 +120,84 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest { val result = defaultCreateRoomFromLocalRoomTask.execute(params) // Then - verifyTombstoneEvent(null) + fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID) // CreateRoomTask has been called with the initial CreateRoomParams coVerify { createRoomTask.execute(aCreateRoomParams) } // The resulting roomId matches the roomId returned by the createRoomTask result shouldBeEqualTo A_ROOM_ID - // A tombstone state event has been created - coVerify { CurrentStateEventEntity.getOrCreate(realm = any(), roomId = A_LOCAL_ROOM_ID, stateKey = any(), type = EventType.STATE_ROOM_TOMBSTONE) } + // The room creation state has correctly been updated + verifyOrder { + aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING + aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATED + } + // The local room summary has been updated with the created room id + verify { aLocalRoomSummaryEntity.replacementRoomId = A_ROOM_ID } + aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo A_ROOM_ID + aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED } - private fun givenATombstoneEvent(event: Event?) { - fakeStateEventDataSource.givenGetStateEventReturns(event) + @Test + fun `given a local room id when execute with an exception then the creation state is correctly updated`() = runTest { + // Given + val aCreateRoomParams = mockk(relaxed = true) + givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null) + val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null) + + coEvery { createRoomTask.execute(any()) }.throws(mockk()) + + // When + val params = CreateRoomFromLocalRoomTask.Params(A_LOCAL_ROOM_ID) + tryOrNull { defaultCreateRoomFromLocalRoomTask.execute(params) } + + // Then + fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID) + // CreateRoomTask has been called with the initial CreateRoomParams + coVerify { createRoomTask.execute(aCreateRoomParams) } + // The room creation state has correctly been updated + verifyOrder { + aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING + aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.FAILURE + } + // The local room summary has been updated with the created room id + aLocalRoomSummaryEntity.replacementRoomId.shouldBeNull() + aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.FAILURE } - private fun givenALocalRoomSummaryEntity(localRoomSummaryEntity: LocalRoomSummaryEntity) { + private fun givenALocalRoomSummary( + aCreateRoomParams: CreateRoomParams, + aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED, + aReplacementRoomId: String? = null + ): LocalRoomSummary { + val aLocalRoomSummary = LocalRoomSummary( + roomId = A_LOCAL_ROOM_ID, + roomSummary = mockk(relaxed = true), + createRoomParams = aCreateRoomParams, + creationState = aCreationState, + replacementRoomId = aReplacementRoomId, + ) + fakeRoomSummaryDataSource.givenGetLocalRoomSummaryReturns(A_LOCAL_ROOM_ID, aLocalRoomSummary) + return aLocalRoomSummary + } + + private fun givenALocalRoomSummaryEntity( + aCreateRoomParams: CreateRoomParams, + aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED, + aReplacementRoomId: String? = null + ): LocalRoomSummaryEntity { + val aLocalRoomSummaryEntity = spyk(LocalRoomSummaryEntity( + roomId = A_LOCAL_ROOM_ID, + roomSummaryEntity = mockk(relaxed = true), + replacementRoomId = aReplacementRoomId, + ).apply { + createRoomParams = aCreateRoomParams + creationState = aCreationState + }) every { fakeMonarchy.fakeRealm.instance .where() .equalTo(LocalRoomSummaryEntityFields.ROOM_ID, A_LOCAL_ROOM_ID) .findFirst() - } returns localRoomSummaryEntity - } - - private fun verifyTombstoneEvent(expectedRoomId: String?) { - fakeStateEventDataSource.verifyGetStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty) - fakeStateEventDataSource.instance.getStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty) - ?.content.toModel() - ?.replacementRoomId shouldBeEqualTo expectedRoomId + } returns aLocalRoomSummaryEntity + return aLocalRoomSummaryEntity } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt index 2d501f12af..93999458c6 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt @@ -47,6 +47,11 @@ internal class FakeMonarchy { } coAnswers { firstArg().doWithRealm(fakeRealm.instance) } + coEvery { + instance.runTransactionSync(any()) + } coAnswers { + firstArg().execute(fakeRealm.instance) + } every { instance.realmConfiguration } returns mockk() } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRoomSummaryDataSource.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRoomSummaryDataSource.kt new file mode 100644 index 0000000000..c7b70a3ad5 --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRoomSummaryDataSource.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.test.fakes + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary +import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource + +internal class FakeRoomSummaryDataSource { + + val instance: RoomSummaryDataSource = mockk() + + fun givenGetLocalRoomSummaryReturns(roomId: String?, localRoomSummary: LocalRoomSummary?) { + every { instance.getLocalRoomSummary(roomId = roomId ?: any()) } returns localRoomSummary + } + + fun verifyGetLocalRoomSummary(roomId: String) { + verify { instance.getLocalRoomSummary(roomId) } + } +} diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js index c7db52fa19..6314ec8f68 100644 --- a/tools/danger/dangerfile.js +++ b/tools/danger/dangerfile.js @@ -118,3 +118,10 @@ if (hasPngs) { if (github.requested_reviewers.users.length == 0 && !pr.draft) { warn("Please add a reviewer to your PR.") } + +// Check that translations have not been modified by developers +if (user != "RiotTranslateBot") { + if (editedFiles.some(file => file.endsWith("strings.xml") && !file.endsWith("values/strings.xml"))) { + fail("Some translation files have been edited. Only user `RiotTranslateBot` (i.e. translations coming from Weblate) is allowed to do that.\nPlease read more about translations management [in the doc](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#internationalisation).") + } +} diff --git a/tools/emojis/emoji_picker_datasource_formatted.json b/tools/emojis/emoji_picker_datasource_formatted.json index 41465a442f..c00bd10371 100644 --- a/tools/emojis/emoji_picker_datasource_formatted.json +++ b/tools/emojis/emoji_picker_datasource_formatted.json @@ -54,6 +54,7 @@ "grimacing-face", "face-exhaling", "lying-face", + "shaking-face", "relieved-face", "pensive-face", "sleepy-face", @@ -104,7 +105,7 @@ "tired-face", "yawning-face", "face-with-steam-from-nose", - "pouting-face", + "enraged-face", "angry-face", "face-with-symbols-on-mouth", "smiling-face-with-horns", @@ -131,7 +132,6 @@ "seenoevil-monkey", "hearnoevil-monkey", "speaknoevil-monkey", - "kiss-mark", "love-letter", "heart-with-arrow", "heart-with-ribbon", @@ -146,14 +146,18 @@ "heart-on-fire", "mending-heart", "red-heart", + "pink-heart", "orange-heart", "yellow-heart", "green-heart", "blue-heart", + "light-blue-heart", "purple-heart", "brown-heart", "black-heart", + "grey-heart", "white-heart", + "kiss-mark", "hundred-points", "anger-symbol", "collision", @@ -161,7 +165,6 @@ "sweat-droplets", "dashing-away", "hole", - "bomb", "speech-balloon", "eye-in-speech-bubble", "left-speech-bubble", @@ -183,6 +186,8 @@ "leftwards-hand", "palm-down-hand", "palm-up-hand", + "leftwards-pushing-hand", + "rightwards-pushing-hand", "ok-hand", "pinched-fingers", "pinching-hand", @@ -561,6 +566,8 @@ "tiger", "leopard", "horse-face", + "moose", + "donkey", "horse", "unicorn", "zebra", @@ -623,6 +630,9 @@ "flamingo", "peacock", "parrot", + "wing", + "black-bird", + "goose", "frog", "crocodile", "turtle", @@ -643,6 +653,7 @@ "octopus", "spiral-shell", "coral", + "jellyfish", "snail", "butterfly", "bug", @@ -670,6 +681,7 @@ "sunflower", "blossom", "tulip", + "hyacinth", "seedling", "potted-plant", "evergreen-tree", @@ -684,7 +696,8 @@ "fallen-leaf", "leaf-fluttering-in-wind", "empty-nest", - "nest-with-eggs" + "nest-with-eggs", + "mushroom" ] }, { @@ -722,10 +735,11 @@ "broccoli", "garlic", "onion", - "mushroom", "peanuts", "beans", "chestnut", + "ginger-root", + "pea-pod", "bread", "croissant", "baguette-bread", @@ -1110,11 +1124,10 @@ "bullseye", "yoyo", "kite", + "water-pistol", "pool-8-ball", "crystal-ball", "magic-wand", - "nazar-amulet", - "hamsa", "video-game", "joystick", "slot-machine", @@ -1165,6 +1178,7 @@ "shorts", "bikini", "womans-clothes", + "folding-hand-fan", "purse", "handbag", "clutch-bag", @@ -1179,6 +1193,7 @@ "womans-sandal", "ballet-shoes", "womans-boot", + "hair-pick", "crown", "womans-hat", "top-hat", @@ -1217,6 +1232,8 @@ "banjo", "drum", "long-drum", + "maracas", + "flute", "mobile-phone", "mobile-phone-with-arrow", "telephone", @@ -1336,7 +1353,7 @@ "hammer-and-wrench", "dagger", "crossed-swords", - "water-pistol", + "bomb", "boomerang", "bow-and-arrow", "shield", @@ -1397,6 +1414,8 @@ "coffin", "headstone", "funeral-urn", + "nazar-amulet", + "hamsa", "moai", "placard", "identification-card" @@ -1465,6 +1484,7 @@ "peace-symbol", "menorah", "dotted-sixpointed-star", + "khanda", "aries", "taurus", "gemini", @@ -1500,6 +1520,7 @@ "dim-button", "bright-button", "antenna-bars", + "wireless", "vibration-mode", "mobile-phone-off", "female-sign", @@ -2050,7 +2071,7 @@ ] }, "melting-face": { - "a": "⊛ Melting Face", + "a": "Melting Face", "b": "1FAE0", "j": [ "disappear", @@ -2345,7 +2366,7 @@ ] }, "face-with-open-eyes-and-hand-over-mouth": { - "a": "⊛ Face with Open Eyes and Hand over Mouth", + "a": "Face with Open Eyes and Hand over Mouth", "b": "1FAE2", "j": [ "amazement", @@ -2360,7 +2381,7 @@ ] }, "face-with-peeking-eye": { - "a": "⊛ Face with Peeking Eye", + "a": "Face with Peeking Eye", "b": "1FAE3", "j": [ "captivated", @@ -2368,7 +2389,8 @@ "stare", "scared", "frightening", - "embarrassing" + "embarrassing", + "shy" ] }, "shushing-face": { @@ -2393,10 +2415,10 @@ ] }, "saluting-face": { - "a": "⊛ Saluting Face", + "a": "Saluting Face", "b": "1FAE1", "j": [ - "ok", + "OK", "salute", "sunny", "troops", @@ -2469,7 +2491,7 @@ ] }, "dotted-line-face": { - "a": "⊛ Dotted Line Face", + "a": "Dotted Line Face", "b": "1FAE5", "j": [ "depressed", @@ -2569,6 +2591,17 @@ "pinocchio" ] }, + "shaking-face": { + "a": "⊛ Shaking Face", + "b": "1FAE8", + "j": [ + "earthquake", + "face", + "shaking", + "shock", + "vibrate" + ] + }, "relieved-face": { "a": "Relieved Face", "b": "1F60C", @@ -2598,6 +2631,7 @@ "b": "1F62A", "j": [ "face", + "good night", "sleep", "tired", "rest", @@ -2617,11 +2651,13 @@ "b": "1F634", "j": [ "face", + "good night", "sleep", - "zzz", + "ZZZ", "tired", "sleepy", - "night" + "night", + "zzz" ] }, "face-with-medical-mask": { @@ -2851,9 +2887,10 @@ "a": "Face with Monocle", "b": "1F9D0", "j": [ + "face", + "monocle", "stuffy", - "wealthy", - "face" + "wealthy" ] }, "confused-face": { @@ -2871,7 +2908,7 @@ ] }, "face-with-diagonal-mouth": { - "a": "⊛ Face with Diagonal Mouth", + "a": "Face with Diagonal Mouth", "b": "1FAE4", "j": [ "disappointed", @@ -2980,7 +3017,7 @@ ] }, "face-holding-back-tears": { - "a": "⊛ Face Holding Back Tears", + "a": "Face Holding Back Tears", "b": "1F979", "j": [ "angry", @@ -3191,16 +3228,18 @@ "pride" ] }, - "pouting-face": { - "a": "Pouting Face", + "enraged-face": { + "a": "Enraged Face", "b": "1F621", "j": [ "angry", + "enraged", "face", "mad", "pouting", "rage", "red", + "pouting_face", "hate", "despise" ] @@ -3578,19 +3617,6 @@ "omg" ] }, - "kiss-mark": { - "a": "Kiss Mark", - "b": "1F48B", - "j": [ - "kiss", - "lips", - "face", - "love", - "like", - "affection", - "valentines" - ] - }, "love-letter": { "a": "Love Letter", "b": "1F48C", @@ -3764,6 +3790,17 @@ "valentines" ] }, + "pink-heart": { + "a": "⊛ Pink Heart", + "b": "1FA77", + "j": [ + "cute", + "heart", + "like", + "love", + "pink" + ] + }, "orange-heart": { "a": "Orange Heart", "b": "1F9E1", @@ -3808,6 +3845,17 @@ "valentines" ] }, + "light-blue-heart": { + "a": "⊛ Light Blue Heart", + "b": "1FA75", + "j": [ + "cyan", + "heart", + "light blue", + "light blue heart", + "teal" + ] + }, "purple-heart": { "a": "Purple Heart", "b": "1F49C", @@ -3837,6 +3885,17 @@ "wicked" ] }, + "grey-heart": { + "a": "⊛ Grey Heart", + "b": "1FA76", + "j": [ + "gray", + "grey heart", + "heart", + "silver", + "slate" + ] + }, "white-heart": { "a": "White Heart", "b": "1F90D", @@ -3846,6 +3905,19 @@ "pure" ] }, + "kiss-mark": { + "a": "Kiss Mark", + "b": "1F48B", + "j": [ + "kiss", + "lips", + "face", + "love", + "like", + "affection", + "valentines" + ] + }, "hundred-points": { "a": "Hundred Points", "b": "1F4AF", @@ -3930,17 +4002,6 @@ "embarrassing" ] }, - "bomb": { - "a": "Bomb", - "b": "1F4A3", - "j": [ - "comic", - "boom", - "explode", - "explosion", - "terrorism" - ] - }, "speech-balloon": { "a": "Speech Balloon", "b": "1F4AC", @@ -3960,8 +4021,10 @@ "a": "Eye in Speech Bubble", "b": "1F441-FE0F-200D-1F5E8-FE0F", "j": [ + "balloon", + "bubble", "eye", - "speech bubble", + "speech", "witness", "info" ] @@ -3970,6 +4033,8 @@ "a": "Left Speech Bubble", "b": "1F5E8", "j": [ + "balloon", + "bubble", "dialog", "speech", "words", @@ -4010,7 +4075,9 @@ "b": "1F4A4", "j": [ "comic", + "good night", "sleep", + "ZZZ", "sleepy", "tired", "dream" @@ -4080,7 +4147,7 @@ ] }, "rightwards-hand": { - "a": "⊛ Rightwards Hand", + "a": "Rightwards Hand", "b": "1FAF1", "j": [ "hand", @@ -4091,7 +4158,7 @@ ] }, "leftwards-hand": { - "a": "⊛ Leftwards Hand", + "a": "Leftwards Hand", "b": "1FAF2", "j": [ "hand", @@ -4102,7 +4169,7 @@ ] }, "palm-down-hand": { - "a": "⊛ Palm Down Hand", + "a": "Palm Down Hand", "b": "1FAF3", "j": [ "dismiss", @@ -4112,7 +4179,7 @@ ] }, "palm-up-hand": { - "a": "⊛ Palm Up Hand", + "a": "Palm Up Hand", "b": "1FAF4", "j": [ "beckon", @@ -4123,6 +4190,32 @@ "demand" ] }, + "leftwards-pushing-hand": { + "a": "⊛ Leftwards Pushing Hand", + "b": "1FAF7", + "j": [ + "high five", + "leftward", + "leftwards pushing hand", + "push", + "refuse", + "stop", + "wait" + ] + }, + "rightwards-pushing-hand": { + "a": "⊛ Rightwards Pushing Hand", + "b": "1FAF8", + "j": [ + "high five", + "push", + "refuse", + "rightward", + "rightwards pushing hand", + "stop", + "wait" + ] + }, "ok-hand": { "a": "Ok Hand", "b": "1F44C", @@ -4186,7 +4279,7 @@ ] }, "hand-with-index-finger-and-thumb-crossed": { - "a": "⊛ Hand with Index Finger and Thumb Crossed", + "a": "Hand with Index Finger and Thumb Crossed", "b": "1FAF0", "j": [ "expensive", @@ -4228,6 +4321,8 @@ "j": [ "call", "hand", + "hang loose", + "Shaka", "hands", "gesture", "shaka" @@ -4313,7 +4408,7 @@ ] }, "index-pointing-at-the-viewer": { - "a": "⊛ Index Pointing at the Viewer", + "a": "Index Pointing at the Viewer", "b": "1FAF5", "j": [ "point", @@ -4429,7 +4524,7 @@ ] }, "heart-hands": { - "a": "⊛ Heart Hands", + "a": "Heart Hands", "b": "1FAF6", "j": [ "love", @@ -4686,7 +4781,7 @@ ] }, "biting-lip": { - "a": "⊛ Biting Lip", + "a": "Biting Lip", "b": "1FAE6", "j": [ "anxious", @@ -6088,7 +6183,7 @@ ] }, "person-with-crown": { - "a": "⊛ Person with Crown", + "a": "Person with Crown", "b": "1FAC5", "j": [ "monarch", @@ -6262,7 +6357,7 @@ ] }, "pregnant-man": { - "a": "⊛ Pregnant Man", + "a": "Pregnant Man", "b": "1FAC3", "j": [ "belly", @@ -6273,7 +6368,7 @@ ] }, "pregnant-person": { - "a": "⊛ Pregnant Person", + "a": "Pregnant Person", "b": "1FAC4", "j": [ "belly", @@ -6669,7 +6764,7 @@ ] }, "troll": { - "a": "⊛ Troll", + "a": "Troll", "b": "1F9CC", "j": [ "fairy tale", @@ -7633,6 +7728,7 @@ "a": "Person in Bed", "b": "1F6CC", "j": [ + "good night", "hotel", "sleep", "bed", @@ -8514,6 +8610,30 @@ "nature" ] }, + "moose": { + "a": "⊛ Moose", + "b": "1FACE", + "j": [ + "animal", + "antlers", + "elk", + "mammal", + "moose" + ] + }, + "donkey": { + "a": "⊛ Donkey", + "b": "1FACF", + "j": [ + "animal", + "ass", + "burro", + "donkey", + "mammal", + "mule", + "stubborn" + ] + }, "horse": { "a": "Horse", "b": "1F40E", @@ -9180,6 +9300,40 @@ "nature" ] }, + "wing": { + "a": "⊛ Wing", + "b": "1FABD", + "j": [ + "angelic", + "aviation", + "bird", + "flying", + "mythology", + "wing" + ] + }, + "black-bird": { + "a": "⊛ Black Bird", + "b": "1F426-200D-2B1B", + "j": [ + "bird", + "black", + "crow", + "raven", + "rook" + ] + }, + "goose": { + "a": "⊛ Goose", + "b": "1FABF", + "j": [ + "bird", + "fowl", + "goose", + "honk", + "silly" + ] + }, "frog": { "a": "Frog", "b": "1F438", @@ -9410,7 +9564,7 @@ ] }, "coral": { - "a": "⊛ Coral", + "a": "Coral", "b": "1FAB8", "j": [ "ocean", @@ -9418,6 +9572,19 @@ "sea" ] }, + "jellyfish": { + "a": "⊛ Jellyfish", + "b": "1FABC", + "j": [ + "burn", + "invertebrate", + "jelly", + "jellyfish", + "marine", + "ouch", + "stinger" + ] + }, "snail": { "a": "Snail", "b": "1F40C", @@ -9621,7 +9788,7 @@ ] }, "lotus": { - "a": "⊛ Lotus", + "a": "Lotus", "b": "1FAB7", "j": [ "Buddhism", @@ -9662,7 +9829,8 @@ "flower", "wilted", "plant", - "nature" + "nature", + "rose" ] }, "hibiscus": { @@ -9709,6 +9877,18 @@ "spring" ] }, + "hyacinth": { + "a": "⊛ Hyacinth", + "b": "1FABB", + "j": [ + "bluebonnet", + "flower", + "hyacinth", + "lavender", + "lupine", + "snapdragon" + ] + }, "seedling": { "a": "Seedling", "b": "1F331", @@ -9873,7 +10053,7 @@ ] }, "empty-nest": { - "a": "⊛ Empty Nest", + "a": "Empty Nest", "b": "1FAB9", "j": [ "nesting", @@ -9881,13 +10061,22 @@ ] }, "nest-with-eggs": { - "a": "⊛ Nest with Eggs", + "a": "Nest with Eggs", "b": "1FABA", "j": [ "nesting", "bird" ] }, + "mushroom": { + "a": "Mushroom", + "b": "1F344", + "j": [ + "toadstool", + "plant", + "vegetable" + ] + }, "grapes": { "a": "Grapes", "b": "1F347", @@ -10199,15 +10388,6 @@ "spice" ] }, - "mushroom": { - "a": "Mushroom", - "b": "1F344", - "j": [ - "toadstool", - "plant", - "vegetable" - ] - }, "peanuts": { "a": "Peanuts", "b": "1F95C", @@ -10219,7 +10399,7 @@ ] }, "beans": { - "a": "⊛ Beans", + "a": "Beans", "b": "1FAD8", "j": [ "food", @@ -10236,6 +10416,28 @@ "squirrel" ] }, + "ginger-root": { + "a": "⊛ Ginger Root", + "b": "1FADA", + "j": [ + "beer", + "ginger root", + "root", + "spice" + ] + }, + "pea-pod": { + "a": "⊛ Pea Pod", + "b": "1FADB", + "j": [ + "beans", + "edamame", + "legume", + "pea", + "pod", + "vegetable" + ] + }, "bread": { "a": "Bread", "b": "1F35E", @@ -11080,7 +11282,8 @@ "tea", "caffeine", "latte", - "espresso" + "espresso", + "mug" ] }, "teapot": { @@ -11255,7 +11458,7 @@ ] }, "pouring-liquid": { - "a": "⊛ Pouring Liquid", + "a": "Pouring Liquid", "b": "1FAD7", "j": [ "drink", @@ -11384,7 +11587,7 @@ ] }, "jar": { - "a": "⊛ Jar", + "a": "Jar", "b": "1FAD9", "j": [ "condiment", @@ -12075,7 +12278,7 @@ ] }, "playground-slide": { - "a": "⊛ Playground Slide", + "a": "Playground Slide", "b": "1F6DD", "j": [ "amusement park", @@ -12606,7 +12809,7 @@ ] }, "wheel": { - "a": "⊛ Wheel", + "a": "Wheel", "b": "1F6DE", "j": [ "circle", @@ -12688,7 +12891,7 @@ ] }, "ring-buoy": { - "a": "⊛ Ring Buoy", + "a": "Ring Buoy", "b": "1F6DF", "j": [ "float", @@ -14683,6 +14886,20 @@ "wind" ] }, + "water-pistol": { + "a": "Water Pistol", + "b": "1F52B", + "j": [ + "gun", + "handgun", + "pistol", + "revolver", + "tool", + "water", + "weapon", + "violence" + ] + }, "pool-8-ball": { "a": "Pool 8 Ball", "b": "1F3B1", @@ -14726,30 +14943,6 @@ "power" ] }, - "nazar-amulet": { - "a": "Nazar Amulet", - "b": "1F9FF", - "j": [ - "bead", - "charm", - "evil-eye", - "nazar", - "talisman" - ] - }, - "hamsa": { - "a": "⊛ Hamsa", - "b": "1FAAC", - "j": [ - "amulet", - "Fatima", - "hand", - "Mary", - "Miriam", - "protection", - "religion" - ] - }, "video-game": { "a": "Video Game", "b": "1F3AE", @@ -14831,7 +15024,7 @@ ] }, "mirror-ball": { - "a": "⊛ Mirror Ball", + "a": "Mirror Ball", "b": "1FAA9", "j": [ "dance", @@ -15252,6 +15445,19 @@ "female" ] }, + "folding-hand-fan": { + "a": "⊛ Folding Hand Fan", + "b": "1FAAD", + "j": [ + "cooling", + "dance", + "fan", + "flutter", + "folding hand fan", + "hot", + "shy" + ] + }, "purse": { "a": "Purse", "b": "1F45B", @@ -15426,6 +15632,16 @@ "fashion" ] }, + "hair-pick": { + "a": "⊛ Hair Pick", + "b": "1FAAE", + "j": [ + "Afro", + "comb", + "hair", + "pick" + ] + }, "crown": { "a": "Crown", "b": "1F451", @@ -15864,6 +16080,30 @@ "music" ] }, + "maracas": { + "a": "⊛ Maracas", + "b": "1FA87", + "j": [ + "instrument", + "maracas", + "music", + "percussion", + "rattle", + "shake" + ] + }, + "flute": { + "a": "⊛ Flute", + "b": "1FA88", + "j": [ + "fife", + "flute", + "music", + "pipe", + "recorder", + "woodwind" + ] + }, "mobile-phone": { "a": "Mobile Phone", "b": "1F4F1", @@ -15941,7 +16181,7 @@ ] }, "low-battery": { - "a": "⊛ Low Battery", + "a": "Low Battery", "b": "1FAAB", "j": [ "electronic", @@ -16054,7 +16294,7 @@ "a": "Optical Disk", "b": "1F4BF", "j": [ - "cd", + "CD", "computer", "disk", "optical", @@ -16068,9 +16308,10 @@ "a": "Dvd", "b": "1F4C0", "j": [ - "blu-ray", + "Blu-ray", "computer", "disk", + "DVD", "optical", "cd", "disc" @@ -17258,18 +17499,15 @@ "weapon" ] }, - "water-pistol": { - "a": "Water Pistol", - "b": "1F52B", + "bomb": { + "a": "Bomb", + "b": "1F4A3", "j": [ - "gun", - "handgun", - "pistol", - "revolver", - "tool", - "water", - "weapon", - "violence" + "comic", + "boom", + "explode", + "explosion", + "terrorism" ] }, "boomerang": { @@ -17584,7 +17822,7 @@ ] }, "crutch": { - "a": "⊛ Crutch", + "a": "Crutch", "b": "1FA7C", "j": [ "cane", @@ -17607,7 +17845,7 @@ ] }, "xray": { - "a": "⊛ X-Ray", + "a": "X-Ray", "b": "1FA7B", "j": [ "bones", @@ -17814,7 +18052,7 @@ ] }, "bubbles": { - "a": "⊛ Bubbles", + "a": "Bubbles", "b": "1FAE7", "j": [ "burp", @@ -17917,6 +18155,30 @@ "rip" ] }, + "nazar-amulet": { + "a": "Nazar Amulet", + "b": "1F9FF", + "j": [ + "bead", + "charm", + "evil-eye", + "nazar", + "talisman" + ] + }, + "hamsa": { + "a": "Hamsa", + "b": "1FAAC", + "j": [ + "amulet", + "Fatima", + "hand", + "Mary", + "Miriam", + "protection", + "religion" + ] + }, "moai": { "a": "Moai", "b": "1F5FF", @@ -17940,7 +18202,7 @@ ] }, "identification-card": { - "a": "⊛ Identification Card", + "a": "Identification Card", "b": "1FAAA", "j": [ "credentials", @@ -17954,7 +18216,7 @@ "a": "Atm Sign", "b": "1F3E7", "j": [ - "atm", + "ATM", "ATM sign", "automated", "bank", @@ -18006,13 +18268,15 @@ "a": "Men’S Room", "b": "1F6B9", "j": [ + "bathroom", "lavatory", "man", "men’s room", "restroom", - "wc", - "men_s_room", "toilet", + "WC", + "men_s_room", + "wc", "blue-square", "gender", "male" @@ -18022,15 +18286,16 @@ "a": "Women’S Room", "b": "1F6BA", "j": [ + "bathroom", "lavatory", "restroom", - "wc", + "toilet", + "WC", "woman", "women’s room", "women_s_room", "purple-square", "female", - "toilet", "loo", "gender" ] @@ -18039,10 +18304,11 @@ "a": "Restroom", "b": "1F6BB", "j": [ + "bathroom", "lavatory", + "toilet", "WC", "blue-square", - "toilet", "refresh", "wc", "gender" @@ -18062,12 +18328,13 @@ "a": "Water Closet", "b": "1F6BE", "j": [ + "bathroom", "closet", "lavatory", "restroom", - "water", - "wc", "toilet", + "water", + "WC", "blue-square" ] }, @@ -18504,8 +18771,7 @@ "b": "1F519", "j": [ "arrow", - "back", - "BACK arrow", + "BACK", "words", "return" ] @@ -18515,8 +18781,7 @@ "b": "1F51A", "j": [ "arrow", - "end", - "END arrow", + "END", "words" ] }, @@ -18526,8 +18791,8 @@ "j": [ "arrow", "mark", - "on", - "ON! arrow", + "ON", + "ON!", "words" ] }, @@ -18536,8 +18801,7 @@ "b": "1F51C", "j": [ "arrow", - "soon", - "SOON arrow", + "SOON", "words" ] }, @@ -18546,8 +18810,7 @@ "b": "1F51D", "j": [ "arrow", - "top", - "TOP arrow", + "TOP", "up", "words", "blue-square" @@ -18689,6 +18952,15 @@ "hexagram" ] }, + "khanda": { + "a": "⊛ Khanda", + "b": "1FAAF", + "j": [ + "khanda", + "religion", + "Sikh" + ] + }, "aries": { "a": "Aries", "b": "2648", @@ -18966,7 +19238,6 @@ "j": [ "arrow", "button", - "red", "blue-square", "triangle", "direction", @@ -18993,7 +19264,6 @@ "arrow", "button", "down", - "red", "blue-square", "direction", "bottom" @@ -19103,6 +19373,16 @@ "bars" ] }, + "wireless": { + "a": "⊛ Wireless", + "b": "1F6DC", + "j": [ + "computer", + "internet", + "network", + "wireless" + ] + }, "vibration-mode": { "a": "Vibration Mode", "b": "1F4F3", @@ -19213,7 +19493,7 @@ ] }, "heavy-equals-sign": { - "a": "⊛ Heavy Equals Sign", + "a": "Heavy Equals Sign", "b": "1F7F0", "j": [ "equality", @@ -19592,7 +19872,7 @@ "a": "Copyright", "b": "00A9", "j": [ - "c", + "C", "ip", "license", "circle", @@ -19604,7 +19884,7 @@ "a": "Registered", "b": "00AE", "j": [ - "r", + "R", "alphabet", "circle" ] @@ -19614,7 +19894,7 @@ "b": "2122", "j": [ "mark", - "tm", + "TM", "trademark", "brand", "law", @@ -19812,7 +20092,7 @@ "a": "A Button (Blood Type)", "b": "1F170", "j": [ - "a", + "A", "A button (blood type)", "blood type", "a_button", @@ -19825,7 +20105,7 @@ "a": "Ab Button (Blood Type)", "b": "1F18E", "j": [ - "ab", + "AB", "AB button (blood type)", "blood type", "ab_button", @@ -19837,7 +20117,7 @@ "a": "B Button (Blood Type)", "b": "1F171", "j": [ - "b", + "B", "B button (blood type)", "blood type", "b_button", @@ -19850,7 +20130,7 @@ "a": "Cl Button", "b": "1F191", "j": [ - "cl", + "CL", "CL button", "alphabet", "words", @@ -19861,7 +20141,7 @@ "a": "Cool Button", "b": "1F192", "j": [ - "cool", + "COOL", "COOL button", "words", "blue-square" @@ -19871,7 +20151,7 @@ "a": "Free Button", "b": "1F193", "j": [ - "free", + "FREE", "FREE button", "blue-square", "words" @@ -19891,7 +20171,7 @@ "a": "Id Button", "b": "1F194", "j": [ - "id", + "ID", "ID button", "identity", "purple-square", @@ -19904,7 +20184,7 @@ "j": [ "circle", "circled M", - "m", + "M", "alphabet", "blue-circle", "letter" @@ -19914,7 +20194,7 @@ "a": "New Button", "b": "1F195", "j": [ - "new", + "NEW", "NEW button", "blue-square", "words", @@ -19925,7 +20205,7 @@ "a": "Ng Button", "b": "1F196", "j": [ - "ng", + "NG", "NG button", "blue-square", "words", @@ -19938,7 +20218,7 @@ "b": "1F17E", "j": [ "blood type", - "o", + "O", "O button (blood type)", "o_button", "alphabet", @@ -19962,6 +20242,7 @@ "a": "P Button", "b": "1F17F", "j": [ + "P", "P button", "parking", "cars", @@ -19975,7 +20256,7 @@ "b": "1F198", "j": [ "help", - "sos", + "SOS", "SOS button", "red-square", "words", @@ -19988,7 +20269,8 @@ "b": "1F199", "j": [ "mark", - "up", + "UP", + "UP!", "UP! button", "blue-square", "above", @@ -20000,7 +20282,7 @@ "b": "1F19A", "j": [ "versus", - "vs", + "VS", "VS button", "words", "orange-square" diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index b4b6ebc12f..3d3b073749 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -19,6 +19,9 @@ + + + @@ -77,6 +80,7 @@ + @@ -87,6 +91,7 @@ + @@ -104,6 +109,9 @@ + + + diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 2368586bfb..a4bc105a1d 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -32,11 +32,11 @@ knit { // Note: 2 digits max for each value ext.versionMajor = 1 -ext.versionMinor = 4 +ext.versionMinor = 5 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 36 +ext.versionPatch = 2 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' @@ -191,7 +191,7 @@ android { // Known limitation: it does not modify the value in the BuildConfig.java generated file // See https://issuetracker.google.com/issues/171133218 output.versionCodeOverride = baseVariantVersion + baseAbiVersionCode - print "ABI " + output.getFilter(OutputFile.ABI) + " \t-> VersionCode = " + output.versionCodeOverride + "\n" + print "ABI " + output.getFilter(OutputFile.ABI) + " \t-> VersionCode = " + output.versionCode + "\n" output.outputFileName = output.outputFileName.replace("vector-app", "vector") } } @@ -291,6 +291,12 @@ android { } } + sourceSets { + nightly { + java.srcDirs += "src/release/java" + } + } + flavorDimensions "store" productFlavors { @@ -349,11 +355,39 @@ android { dependencies { implementation project(':vector') implementation project(':vector-config') + debugImplementation project(':library:ui-styles') implementation libs.dagger.hilt implementation 'androidx.multidex:multidex:2.0.1' implementation "androidx.sharetarget:sharetarget:1.1.0" + // Flipper, debug builds only + debugImplementation(libs.flipper.flipper) { + exclude group: 'com.facebook.fbjni', module: 'fbjni' + } + debugImplementation(libs.flipper.flipperNetworkPlugin) { + exclude group: 'com.facebook.fbjni', module: 'fbjni' + } + debugImplementation 'com.facebook.soloader:soloader:0.10.4' + debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0" + + gplayImplementation "com.google.android.gms:play-services-location:20.0.0" + // UnifiedPush gplay flavor only + gplayImplementation('com.google.firebase:firebase-messaging:23.0.8') { + exclude group: 'com.google.firebase', module: 'firebase-core' + exclude group: 'com.google.firebase', module: 'firebase-analytics' + exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' + } + + // Nightly + // API-only library + gplayImplementation libs.google.appdistributionApi + // Full SDK implementation + gplayImplementation libs.google.appdistribution + + // OSS License, gplay flavor only + gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' kapt libs.dagger.hiltCompiler + kapt libs.airbnb.epoxyProcessor androidTestImplementation libs.androidx.testCore androidTestImplementation libs.androidx.testRunner @@ -378,5 +412,6 @@ dependencies { androidTestImplementation libs.androidx.fragmentTesting androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10" debugImplementation libs.androidx.fragmentTesting + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' } diff --git a/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt b/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt index 6f9d6cdde9..3f82ce1ef0 100644 --- a/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt @@ -26,6 +26,7 @@ import androidx.test.filters.LargeTest import com.adevinta.android.barista.internal.viewaction.SleepViewAction import im.vector.app.features.MainActivity import im.vector.app.ui.robot.ElementRobot +import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain @@ -34,6 +35,7 @@ import java.util.UUID @RunWith(AndroidJUnit4::class) @LargeTest +@Ignore("Disabled temporarily so that we can unblock other PRs.") class CantVerifyTest { @get:Rule diff --git a/vector-app/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt b/vector-app/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt index 48fc1343b1..d8873a71a4 100644 --- a/vector-app/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt +++ b/vector-app/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt @@ -20,11 +20,13 @@ import androidx.test.platform.app.InstrumentationRegistry import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.MatrixConfiguration +import org.matrix.android.sdk.api.SyncConfig fun getMatrixInstance(): Matrix { val context = InstrumentationRegistry.getInstrumentation().targetContext val configuration = MatrixConfiguration( - roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context) + roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context), + syncConfig = SyncConfig(longPollTimeout = 5_000L), ) return Matrix(context, configuration) } diff --git a/vector-app/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt b/vector-app/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt index 068c9fb646..5e131479bf 100644 --- a/vector-app/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt +++ b/vector-app/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt @@ -92,7 +92,6 @@ private fun useMediaStoreScreenshotStorage( } } -@Suppress("DEPRECATION") private fun usePublicExternalScreenshotStorage( contentValues: ContentValues, contentResolver: ContentResolver, diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 9434006060..d4878b8dcc 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -21,6 +21,7 @@ import androidx.test.espresso.IdlingPolicies import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import im.vector.app.R import im.vector.app.espresso.tools.ScreenshotFailureRule @@ -28,6 +29,7 @@ import im.vector.app.features.MainActivity import im.vector.app.getString import im.vector.app.ui.robot.ElementRobot import im.vector.app.ui.robot.settings.labs.LabFeature +import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import im.vector.app.ui.robot.withDeveloperMode import org.junit.Rule import org.junit.Test @@ -49,7 +51,14 @@ class UiAllScreensSanityTest { .around(GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)) .around(ScreenshotFailureRule()) - private val elementRobot = ElementRobot() + private val elementRobot = ElementRobot( + LabFeaturesPreferences( + InstrumentationRegistry.getInstrumentation() + .targetContext + .resources + .getBoolean(R.bool.settings_labs_new_app_layout_default) + ) + ) // Last passing: // 2020-11-09 @@ -101,11 +110,11 @@ class UiAllScreensSanityTest { val spaceName = UUID.randomUUID().toString() elementRobot.space { - createSpace { + createSpace(true) { createAndCrawl(spaceName) } val publicSpaceName = UUID.randomUUID().toString() - createSpace { + createSpace(false) { createPublicSpace(publicSpaceName) } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt index 528589d616..86709a75a5 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt @@ -37,8 +37,6 @@ import im.vector.app.espresso.tools.clickOnPreference import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilViewVisible -import im.vector.app.features.DefaultVectorFeatures -import im.vector.app.features.VectorFeatures import im.vector.app.features.createdirect.CreateDirectRoomActivity import im.vector.app.features.home.HomeActivity import im.vector.app.features.onboarding.OnboardingActivity @@ -46,14 +44,14 @@ import im.vector.app.features.settings.VectorSettingsActivity import im.vector.app.initialSyncIdlingResource import im.vector.app.ui.robot.settings.SettingsRobot import im.vector.app.ui.robot.settings.labs.LabFeature +import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import im.vector.app.ui.robot.space.SpaceRobot import im.vector.app.withIdlingResource import timber.log.Timber -class ElementRobot { - - var features: VectorFeatures = DefaultVectorFeatures() - +class ElementRobot( + private val labsPreferences: LabFeaturesPreferences = LabFeaturesPreferences(false) +) { fun onboarding(block: OnboardingRobot.() -> Unit) { block(OnboardingRobot()) } @@ -84,16 +82,28 @@ class ElementRobot { } fun settings(shouldGoBack: Boolean = true, block: SettingsRobot.() -> Unit) { - openDrawer() - clickOn(R.id.homeDrawerHeaderSettingsView) + if (labsPreferences.isNewAppLayoutEnabled) { + onView(withId((R.id.avatar))).perform(click()) + } else { + openDrawer() + clickOn(R.id.homeDrawerHeaderSettingsView) + } + block(SettingsRobot()) if (shouldGoBack) pressBack() waitUntilViewVisible(withId(R.id.roomListContainer)) } fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) { - clickOn(R.id.bottom_action_people) - clickOn(R.id.createChatRoomButton) + if (labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.newLayoutCreateChatButton) + waitUntilDialogVisible(withId(R.id.start_chat)) + clickOn(R.id.start_chat) + } else { + clickOn(R.id.bottom_action_people) + clickOn(R.id.createChatRoomButton) + } + waitUntilActivityVisible { waitUntilViewVisible(withId(R.id.userListSearch)) } @@ -104,14 +114,19 @@ class ElementRobot { } fun newRoom(block: NewRoomRobot.() -> Unit) { - clickOn(R.id.bottom_action_rooms) - RoomListRobot().newRoom { block() } + if (!labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.bottom_action_rooms) + } + RoomListRobot(labsPreferences).newRoom { block() } waitUntilViewVisible(withId(R.id.roomListContainer)) } fun roomList(block: RoomListRobot.() -> Unit) { - clickOn(R.id.bottom_action_rooms) - block(RoomListRobot()) + if (!labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.bottom_action_rooms) + } + + block(RoomListRobot(labsPreferences)) waitUntilViewVisible(withId(R.id.roomListContainer)) } @@ -152,7 +167,7 @@ class ElementRobot { } fun signout(expectSignOutWarning: Boolean) { - if (features.isNewAppLayoutEnabled()) { + if (labsPreferences.isNewAppLayoutEnabled) { onView(withId((R.id.avatar))) .perform(click()) waitUntilActivityVisible { @@ -202,7 +217,7 @@ class ElementRobot { } fun space(block: SpaceRobot.() -> Unit) { - block(SpaceRobot()) + block(SpaceRobot(labsPreferences)) } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt index 09ff1162c0..0cea26d5cc 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt @@ -21,10 +21,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import im.vector.app.R import im.vector.app.espresso.tools.waitUntilViewVisible +import im.vector.app.features.DefaultVectorFeatures +import im.vector.app.features.VectorFeatures +import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences class NewRoomRobot( - var createdRoom: Boolean = false + var createdRoom: Boolean = false, + private val labsPreferences: LabFeaturesPreferences ) { + private val features: VectorFeatures = DefaultVectorFeatures() fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) { clickOn(R.string.create_new_room) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt index e72535c116..1f1a799db3 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt @@ -33,7 +33,6 @@ import im.vector.app.features.DefaultVectorFeatures import im.vector.app.waitForView class OnboardingRobot { - private val defaultVectorFeatures = DefaultVectorFeatures() fun crawl() { diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt index dc07f06202..e4984aeed0 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt @@ -27,9 +27,11 @@ import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import im.vector.app.R import im.vector.app.espresso.tools.waitUntilActivityVisible +import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.features.roomdirectory.RoomDirectoryActivity +import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences -class RoomListRobot { +class RoomListRobot(private val labsPreferences: LabFeaturesPreferences) { fun openRoom(roomName: String, block: RoomDetailRobot.() -> Unit) { clickOn(roomName) @@ -49,11 +51,17 @@ class RoomListRobot { } fun newRoom(block: NewRoomRobot.() -> Unit) { - clickOn(R.id.createGroupRoomButton) - waitUntilActivityVisible { - BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList) + if (labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.newLayoutCreateChatButton) + waitUntilDialogVisible(ViewMatchers.withId(R.id.create_room)) + clickOn(R.id.create_room) + } else { + clickOn(R.id.createGroupRoomButton) + waitUntilActivityVisible { + BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList) + } } - val newRoomRobot = NewRoomRobot() + val newRoomRobot = NewRoomRobot(false, labsPreferences) block(newRoomRobot) if (!newRoomRobot.createdRoom) { pressBack() diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/labs/LabFeaturesPreferences.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/labs/LabFeaturesPreferences.kt new file mode 100644 index 0000000000..8f36e7ae23 --- /dev/null +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/labs/LabFeaturesPreferences.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.ui.robot.settings.labs + +data class LabFeaturesPreferences(val isNewAppLayoutEnabled: Boolean) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt index 018f3097ba..e5147c2085 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt @@ -31,6 +31,7 @@ import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.HomeActivity +import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.spaces.manage.SpaceManageActivity class SpaceCreateRobot { @@ -85,7 +86,9 @@ class SpaceCreateRobot { clickOn(R.id.nextButton) waitUntilViewVisible(withId(R.id.recyclerView)) clickOn(R.id.nextButton) - waitUntilDialogVisible(withId(R.id.inviteByMxidButton)) + waitUntilActivityVisible { + waitUntilDialogVisible(withId(R.id.inviteByMxidButton)) + } // close invite dialog pressBack() waitUntilViewVisible(withId(R.id.timelineRecyclerView)) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt index b8a2f4313b..e8ff58ba6a 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt @@ -18,6 +18,8 @@ package im.vector.app.ui.robot.space import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.matcher.ViewMatchers import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn @@ -26,18 +28,44 @@ import com.adevinta.android.barista.internal.viewaction.ClickChildAction import im.vector.app.R import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilViewVisible +import im.vector.app.features.DefaultVectorFeatures +import im.vector.app.features.VectorFeatures +import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import org.hamcrest.Matchers -class SpaceRobot { +class SpaceRobot(private val labsPreferences: LabFeaturesPreferences) { + private val features: VectorFeatures = DefaultVectorFeatures() - fun createSpace(block: SpaceCreateRobot.() -> Unit) { - openDrawer() - clickOn(R.string.create_space) + fun createSpace(isFirstSpace: Boolean, block: SpaceCreateRobot.() -> Unit) { + if (labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.newLayoutOpenSpacesButton) + if (isFirstSpace) { + waitUntilDialogVisible(ViewMatchers.withId(R.id.spaces_empty_group)) + clickOn(R.id.spaces_empty_button) + } else { + waitUntilDialogVisible(ViewMatchers.withId(R.id.groupListView)) + Espresso.onView(ViewMatchers.withId(R.id.groupListView)) + .perform( + RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(ViewMatchers.withId(R.id.plus)), + click() + ).atPosition(0) + ) + } + } else { + openDrawer() + clickOn(R.string.create_space) + } block(SpaceCreateRobot()) } fun spaceMenu(spaceName: String, block: SpaceMenuRobot.() -> Unit) { - openDrawer() + if (labsPreferences.isNewAppLayoutEnabled) { + clickOn(R.id.newLayoutOpenSpacesButton) + waitUntilDialogVisible(ViewMatchers.withId(R.id.groupListView)) + } else { + openDrawer() + } with(SpaceMenuRobot()) { openMenu(spaceName) block() @@ -46,19 +74,32 @@ class SpaceRobot { fun openMenu(spaceName: String) { waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) - Espresso.onView(ViewMatchers.withId(R.id.groupListView)) - .perform( - RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))), - ClickChildAction.clickChildWithId(R.id.groupTmpLeave) - ).atPosition(0) - ) + if (labsPreferences.isNewAppLayoutEnabled) { + Espresso.onView(ViewMatchers.withId(R.id.groupListView)) + .perform( + RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.name), ViewMatchers.withText(spaceName))), + longClick() + ).atPosition(0) + ) + } else { + Espresso.onView(ViewMatchers.withId(R.id.groupListView)) + .perform( + RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))), + ClickChildAction.clickChildWithId(R.id.groupTmpLeave) + ).atPosition(0) + ) + } + waitUntilDialogVisible(ViewMatchers.withId(R.id.spaceNameView)) } fun selectSpace(spaceName: String) { - openDrawer() - waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) + if (!labsPreferences.isNewAppLayoutEnabled) { + openDrawer() + waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) + } clickOn(spaceName) } } diff --git a/vector-app/src/debug/AndroidManifest.xml b/vector-app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..a7867f4081 --- /dev/null +++ b/vector-app/src/debug/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt similarity index 99% rename from vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt index eaaf021989..005e9c499b 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt @@ -34,13 +34,13 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.toast -import im.vector.app.databinding.ActivityDebugMenuBinding import im.vector.app.features.debug.analytics.DebugAnalyticsActivity import im.vector.app.features.debug.features.DebugFeaturesSettingsActivity import im.vector.app.features.debug.leak.DebugMemoryLeaksActivity import im.vector.app.features.debug.sas.DebugSasEmojiActivity import im.vector.app.features.debug.settings.DebugPrivateSettingsActivity import im.vector.app.features.qrcode.QrCodeScannerActivity +import im.vector.application.databinding.ActivityDebugMenuBinding import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkDefaultActivity import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkTestActivity import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkVectorActivity diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt similarity index 97% rename from vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt index 0f00f2daa5..a9be5512e4 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt @@ -23,13 +23,13 @@ import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.onPermissionDeniedDialog import im.vector.app.core.utils.onPermissionDeniedSnackbar import im.vector.app.core.utils.registerForPermissionsResult -import im.vector.app.databinding.ActivityDebugPermissionBinding +import im.vector.application.R +import im.vector.application.databinding.ActivityDebugPermissionBinding import timber.log.Timber @AndroidEntryPoint diff --git a/vector/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt similarity index 97% rename from vector/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt index 59c60e0e15..6e94bce00a 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/TestLinkifyActivity.kt @@ -20,9 +20,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity -import im.vector.app.R -import im.vector.app.databinding.ActivityTestLinkifyBinding -import im.vector.app.databinding.ItemTestLinkifyBinding +import im.vector.application.R +import im.vector.application.databinding.ActivityTestLinkifyBinding +import im.vector.application.databinding.ItemTestLinkifyBinding class TestLinkifyActivity : AppCompatActivity() { diff --git a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsActivity.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsActivity.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt similarity index 97% rename from vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt index eb23fe6383..0fa11d7220 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsFragment.kt @@ -25,7 +25,7 @@ import com.airbnb.mvrx.withState import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.toOnOff import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.FragmentDebugAnalyticsBinding +import im.vector.application.databinding.FragmentDebugAnalyticsBinding import me.gujun.android.span.span class DebugAnalyticsFragment : VectorBaseFragment() { diff --git a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewActions.kt b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewActions.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewActions.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewActions.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewModel.kt b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewModel.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewModel.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewModel.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewState.kt b/vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewState.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewState.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/analytics/DebugAnalyticsViewState.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/FeaturesModule.kt b/vector-app/src/debug/java/im/vector/app/features/debug/di/FeaturesModule.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/di/FeaturesModule.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/di/FeaturesModule.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt b/vector-app/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt similarity index 94% rename from vector/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt index 1e9b88c048..38765bfa9b 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/features/BooleanFeatureItem.kt @@ -23,9 +23,9 @@ import android.widget.Spinner import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass -import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.application.R @EpoxyModelClass abstract class BooleanFeatureItem : VectorEpoxyModel(R.layout.item_feature) { @@ -70,8 +70,8 @@ abstract class BooleanFeatureItem : VectorEpoxyModel( } class Holder : VectorEpoxyHolder() { - val label by bind(im.vector.app.R.id.feature_label) - val optionsSpinner by bind(im.vector.app.R.id.feature_options) + val label by bind(R.id.feature_label) + val optionsSpinner by bind(R.id.feature_options) } interface Listener { diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesSettingsActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesSettingsActivity.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesSettingsActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesSettingsActivity.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt similarity index 94% rename from vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt index c127e3aed6..9118dea1e3 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt @@ -80,15 +80,10 @@ class DebugFeaturesStateFactory @Inject constructor( key = DebugFeatureKeys.forceUsageOfOpusEncoder, factory = VectorFeatures::forceUsageOfOpusEncoder ), - createBooleanFeature( - label = "Start DM on first message", - key = DebugFeatureKeys.startDmOnFirstMsg, - factory = VectorFeatures::shouldStartDmOnFirstMessage - ), createBooleanFeature( label = "Enable New App Layout", key = DebugFeatureKeys.newAppLayoutEnabled, - factory = VectorFeatures::isNewAppLayoutEnabled + factory = VectorFeatures::isNewAppLayoutFeatureEnabled ), createBooleanFeature( label = "Enable New Device Management", diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt similarity index 95% rename from vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index 003b9b8084..c01c058fc6 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -73,11 +73,8 @@ class DebugVectorFeatures( override fun forceUsageOfOpusEncoder(): Boolean = read(DebugFeatureKeys.forceUsageOfOpusEncoder) ?: vectorFeatures.forceUsageOfOpusEncoder() - override fun shouldStartDmOnFirstMessage(): Boolean = read(DebugFeatureKeys.startDmOnFirstMsg) - ?: vectorFeatures.shouldStartDmOnFirstMessage() - - override fun isNewAppLayoutEnabled(): Boolean = read(DebugFeatureKeys.newAppLayoutEnabled) - ?: vectorFeatures.isNewAppLayoutEnabled() + override fun isNewAppLayoutFeatureEnabled(): Boolean = read(DebugFeatureKeys.newAppLayoutEnabled) + ?: vectorFeatures.isNewAppLayoutFeatureEnabled() override fun isNewDeviceManagementEnabled(): Boolean = read(DebugFeatureKeys.newDeviceManagementEnabled) ?: vectorFeatures.isNewDeviceManagementEnabled() diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt similarity index 92% rename from vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt index 5e16182f3c..57138b9a47 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/features/DebugVectorOverrides.kt @@ -66,13 +66,13 @@ class DebugVectorOverrides(private val context: Context) : VectorOverrides { suspend fun setHomeserverCapabilities(block: HomeserverCapabilitiesOverride.() -> HomeserverCapabilitiesOverride) { val capabilitiesOverride = block(forceHomeserverCapabilities.firstOrNull() ?: HomeserverCapabilitiesOverride(null, null)) context.dataStore.edit { settings -> - when (capabilitiesOverride.canChangeDisplayName) { + when (val canChangeDisplayName = capabilitiesOverride.canChangeDisplayName) { null -> settings.remove(forceCanChangeDisplayName) - else -> settings[forceCanChangeDisplayName] = capabilitiesOverride.canChangeDisplayName + else -> settings[forceCanChangeDisplayName] = canChangeDisplayName } - when (capabilitiesOverride.canChangeAvatar) { + when (val canChangeAvatar = capabilitiesOverride.canChangeAvatar) { null -> settings.remove(forceCanChangeAvatar) - else -> settings[forceCanChangeAvatar] = capabilitiesOverride.canChangeAvatar + else -> settings[forceCanChangeAvatar] = canChangeAvatar } } } diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt similarity index 94% rename from vector/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt index 5231e591da..00f74515cc 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/features/EnumFeatureItem.kt @@ -23,9 +23,9 @@ import android.widget.Spinner import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass -import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.application.R @EpoxyModelClass abstract class EnumFeatureItem : VectorEpoxyModel(R.layout.item_feature) { @@ -70,8 +70,8 @@ abstract class EnumFeatureItem : VectorEpoxyModel(R.layo } class Holder : VectorEpoxyHolder() { - val label by bind(im.vector.app.R.id.feature_label) - val optionsSpinner by bind(im.vector.app.R.id.feature_options) + val label by bind(R.id.feature_label) + val optionsSpinner by bind(R.id.feature_options) } interface Listener { diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/FeaturesController.kt b/vector-app/src/debug/java/im/vector/app/features/debug/features/FeaturesController.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/features/FeaturesController.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/features/FeaturesController.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt similarity index 96% rename from vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt index 2abf6487e2..e9afa9aea9 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt @@ -25,7 +25,7 @@ import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint import im.vector.app.core.epoxy.onClick import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.FragmentDebugMemoryLeaksBinding +import im.vector.application.databinding.FragmentDebugMemoryLeaksBinding @AndroidEntryPoint class DebugMemoryLeaksFragment : diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt similarity index 98% rename from vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt index 5432cb0888..26eb1c1025 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt b/vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/sas/DebugSasEmojiActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/sas/DebugSasEmojiActivity.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/sas/DebugSasEmojiActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/sas/DebugSasEmojiActivity.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiController.kt b/vector-app/src/debug/java/im/vector/app/features/debug/sas/SasEmojiController.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiController.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/sas/SasEmojiController.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt b/vector-app/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt similarity index 98% rename from vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt index 179ee35693..bbc438e4b2 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt @@ -21,9 +21,9 @@ import android.widget.TextView import androidx.core.content.ContextCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass -import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.application.R import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsActivity.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsActivity.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsActivity.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt b/vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt similarity index 76% rename from vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt index 38253fe7c2..020c228521 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsFragment.kt @@ -16,6 +16,8 @@ package im.vector.app.features.debug.settings +import android.annotation.SuppressLint +import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -23,7 +25,8 @@ import android.view.ViewGroup import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.FragmentDebugPrivateSettingsBinding +import im.vector.app.features.home.room.list.home.release.ReleaseNotesActivity +import im.vector.application.databinding.FragmentDebugPrivateSettingsBinding class DebugPrivateSettingsFragment : VectorBaseFragment() { @@ -35,7 +38,6 @@ class DebugPrivateSettingsFragment : VectorBaseFragment viewModel.handle(DebugPrivateSettingsViewActions.SetForceLoginFallbackEnabled(isChecked)) } + views.releaseNotesActivityHasBeenDisplayedReset.setOnClickListener { + viewModel.handle(DebugPrivateSettingsViewActions.ResetReleaseNotesActivityHasBeenDisplayed) + } + views.showReleaseNotesActivity.setOnClickListener { + startActivity(Intent(requireActivity(), ReleaseNotesActivity::class.java)) + } } override fun invalidate() = withState(viewModel) { @@ -57,5 +65,7 @@ class DebugPrivateSettingsFragment : VectorBaseFragment(initialState) { @AssistedFactory @@ -43,6 +45,15 @@ class DebugPrivateSettingsViewModel @AssistedInject constructor( init { observeVectorOverrides() + observeReleaseNotesPreferencesStore() + } + + private fun observeReleaseNotesPreferencesStore() { + releaseNotesPreferencesStore.appLayoutOnboardingShown.setOnEach { + copy( + releaseNotesActivityHasBeenDisplayed = it + ) + } } private fun observeVectorOverrides() { @@ -72,6 +83,13 @@ class DebugPrivateSettingsViewModel @AssistedInject constructor( is DebugPrivateSettingsViewActions.SetForceLoginFallbackEnabled -> handleSetForceLoginFallbackEnabled(action) is SetDisplayNameCapabilityOverride -> handleSetDisplayNameCapabilityOverride(action) is SetAvatarCapabilityOverride -> handleSetAvatarCapabilityOverride(action) + DebugPrivateSettingsViewActions.ResetReleaseNotesActivityHasBeenDisplayed -> handleResetReleaseNotesActivityHasBeenDisplayed() + } + } + + private fun handleResetReleaseNotesActivityHasBeenDisplayed() { + viewModelScope.launch { + releaseNotesPreferencesStore.setAppLayoutOnboardingShown(false) } } diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt b/vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt similarity index 93% rename from vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt index 749b11a744..a390c94942 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/settings/DebugPrivateSettingsViewState.kt @@ -22,7 +22,8 @@ import im.vector.app.features.debug.settings.OverrideDropdownView.OverrideDropdo data class DebugPrivateSettingsViewState( val dialPadVisible: Boolean = false, val forceLoginFallback: Boolean = false, - val homeserverCapabilityOverrides: HomeserverCapabilityOverrides = HomeserverCapabilityOverrides() + val homeserverCapabilityOverrides: HomeserverCapabilityOverrides = HomeserverCapabilityOverrides(), + val releaseNotesActivityHasBeenDisplayed: Boolean = false, ) : MavericksState data class HomeserverCapabilityOverrides( diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt b/vector-app/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt similarity index 97% rename from vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt index 7f510ee5e9..2800b7bd8d 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt @@ -24,7 +24,7 @@ import android.view.View import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.LinearLayout -import im.vector.app.databinding.ViewBooleanDropdownBinding +import im.vector.application.databinding.ViewBooleanDropdownBinding class OverrideDropdownView @JvmOverloads constructor( context: Context, diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/PrivateSettingOverrides.kt b/vector-app/src/debug/java/im/vector/app/features/debug/settings/PrivateSettingOverrides.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/features/debug/settings/PrivateSettingOverrides.kt rename to vector-app/src/debug/java/im/vector/app/features/debug/settings/PrivateSettingOverrides.kt diff --git a/vector/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt b/vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt rename to vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt diff --git a/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt b/vector-app/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt similarity index 100% rename from vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt rename to vector-app/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt diff --git a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt b/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt similarity index 85% rename from vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt rename to vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt index 550dc055d9..4edbdd0591 100644 --- a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt +++ b/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -23,7 +23,7 @@ import android.content.IntentFilter import android.content.SharedPreferences import androidx.core.content.edit import im.vector.app.core.debug.DebugReceiver -import im.vector.app.core.di.DefaultSharedPreferences +import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.utils.lsFiles import timber.log.Timber import javax.inject.Inject @@ -31,7 +31,10 @@ import javax.inject.Inject /** * Receiver to handle some command from ADB */ -class VectorDebugReceiver @Inject constructor() : BroadcastReceiver(), DebugReceiver { +class VectorDebugReceiver @Inject constructor( + @DefaultPreferences + private val sharedPreferences: SharedPreferences, +) : BroadcastReceiver(), DebugReceiver { override fun register(context: Context) { context.registerReceiver(this, getIntentFilter(context)) @@ -47,14 +50,14 @@ class VectorDebugReceiver @Inject constructor() : BroadcastReceiver(), DebugRece intent.action?.let { when { it.endsWith(DEBUG_ACTION_DUMP_FILESYSTEM) -> lsFiles(context) - it.endsWith(DEBUG_ACTION_DUMP_PREFERENCES) -> dumpPreferences(context) - it.endsWith(DEBUG_ACTION_ALTER_SCALAR_TOKEN) -> alterScalarToken(context) + it.endsWith(DEBUG_ACTION_DUMP_PREFERENCES) -> dumpPreferences() + it.endsWith(DEBUG_ACTION_ALTER_SCALAR_TOKEN) -> alterScalarToken() } } } - private fun dumpPreferences(context: Context) { - logPrefs("DefaultSharedPreferences", DefaultSharedPreferences.getInstance(context)) + private fun dumpPreferences() { + logPrefs("DefaultSharedPreferences", sharedPreferences) } private fun logPrefs(name: String, sharedPreferences: SharedPreferences?) { @@ -67,8 +70,8 @@ class VectorDebugReceiver @Inject constructor() : BroadcastReceiver(), DebugRece } } - private fun alterScalarToken(context: Context) { - DefaultSharedPreferences.getInstance(context).edit { + private fun alterScalarToken() { + sharedPreferences.edit { // putString("SCALAR_TOKEN_PREFERENCE_KEY" + Matrix.getInstance(context).defaultSession.myUserId, "bad_token") } } diff --git a/vector/src/debug/res/layout/activity_debug_menu.xml b/vector-app/src/debug/res/layout/activity_debug_menu.xml similarity index 100% rename from vector/src/debug/res/layout/activity_debug_menu.xml rename to vector-app/src/debug/res/layout/activity_debug_menu.xml diff --git a/vector/src/debug/res/layout/activity_debug_permission.xml b/vector-app/src/debug/res/layout/activity_debug_permission.xml similarity index 100% rename from vector/src/debug/res/layout/activity_debug_permission.xml rename to vector-app/src/debug/res/layout/activity_debug_permission.xml diff --git a/vector/src/debug/res/layout/activity_test_linkify.xml b/vector-app/src/debug/res/layout/activity_test_linkify.xml similarity index 100% rename from vector/src/debug/res/layout/activity_test_linkify.xml rename to vector-app/src/debug/res/layout/activity_test_linkify.xml diff --git a/vector/src/debug/res/layout/demo_theme_sample.xml b/vector-app/src/debug/res/layout/demo_theme_sample.xml similarity index 100% rename from vector/src/debug/res/layout/demo_theme_sample.xml rename to vector-app/src/debug/res/layout/demo_theme_sample.xml diff --git a/vector/src/debug/res/layout/demo_themes.xml b/vector-app/src/debug/res/layout/demo_themes.xml similarity index 100% rename from vector/src/debug/res/layout/demo_themes.xml rename to vector-app/src/debug/res/layout/demo_themes.xml diff --git a/vector/src/debug/res/layout/fragment_debug_analytics.xml b/vector-app/src/debug/res/layout/fragment_debug_analytics.xml similarity index 100% rename from vector/src/debug/res/layout/fragment_debug_analytics.xml rename to vector-app/src/debug/res/layout/fragment_debug_analytics.xml diff --git a/vector/src/debug/res/layout/fragment_debug_memory_leaks.xml b/vector-app/src/debug/res/layout/fragment_debug_memory_leaks.xml similarity index 100% rename from vector/src/debug/res/layout/fragment_debug_memory_leaks.xml rename to vector-app/src/debug/res/layout/fragment_debug_memory_leaks.xml diff --git a/vector/src/debug/res/layout/fragment_debug_private_settings.xml b/vector-app/src/debug/res/layout/fragment_debug_private_settings.xml similarity index 72% rename from vector/src/debug/res/layout/fragment_debug_private_settings.xml rename to vector-app/src/debug/res/layout/fragment_debug_private_settings.xml index c42ad68dce..55824930bc 100644 --- a/vector/src/debug/res/layout/fragment_debug_private_settings.xml +++ b/vector-app/src/debug/res/layout/fragment_debug_private_settings.xml @@ -49,6 +49,27 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="4dp" /> + + +