Merge branch 'develop' into feature/bma/scroll-to-unread-messages
This commit is contained in:
@@ -44,7 +44,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
# Skip in forks, it doesn't work even with the fallback token
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Add SSH private keys for submodule repositories
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
# Skip in forks
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
concurrency:
|
||||
group: maestro-test
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
name: Dependency analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Add SSH private keys for submodule repositories
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
name: Search for invalid screenshot files
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python 3.12
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
name: Search for invalid dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-konsist-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-konsist-develop-{0}', github.sha) || format('check-konsist-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -134,7 +134,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-compose-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-compose-develop-{0}', github.sha) || format('check-compose-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-lint-develop-{0}', github.sha) || format('check-lint-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-detekt-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-detekt-develop-{0}', github.sha) || format('check-detekt-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-ktlint-develop-{0}', github.sha) || format('check-ktlint-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -295,7 +295,7 @@ jobs:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('check-docs-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-docs-develop-{0}', github.sha) || format('check-docs-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
@@ -319,7 +319,7 @@ jobs:
|
||||
name: Check shell scripts
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run shellcheck
|
||||
@@ -333,7 +333,7 @@ jobs:
|
||||
permissions:
|
||||
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
|
||||
@@ -344,7 +344,7 @@ jobs:
|
||||
needs: [konsist, lint, ktlint, detekt]
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
group: ${{ format('build-release-main-enterprise-{0}', github.sha) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Add SSH private keys for submodule repositories
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
docker-images: true
|
||||
swap-storage: false
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
# Ensure we are building the branch and not the branch after being merged on develop
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
# Skip in forks
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use JDK 21
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python 3.12
|
||||
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
|
||||
# https://github.com/codecov/codecov-action
|
||||
- name: ☂️ Upload coverage reports to codecov
|
||||
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
|
||||
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
Generated
+1
-1
@@ -2,6 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="externalSystemId" value="Gradle" />
|
||||
<option name="version" value="2.3.21" />
|
||||
<option name="version" value="2.4.0" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
Changes in Element X v26.06.2
|
||||
=============================
|
||||
|
||||
Security fixes 🔐
|
||||
-----------------
|
||||
- Fixed an issue with OIDC callback URLs that could cause the app to crash [(GHSA-r4f9-46vw-v7g3)](https://github.com/element-hq/element-x-android/security/advisories/GHSA-r4f9-46vw-v7g3).
|
||||
|
||||
Changes in Element X v26.06.1
|
||||
=============================
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.util.Locale
|
||||
|
||||
plugins {
|
||||
id("io.element.android-compose-application")
|
||||
alias(libs.plugins.kotlin.android)
|
||||
// When using precompiled plugins, we need to apply the firebase plugin like this
|
||||
id(libs.plugins.firebaseAppDistribution.get().pluginId)
|
||||
id("kotlin-parcelize")
|
||||
@@ -189,6 +188,7 @@ android {
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
resValues = true
|
||||
}
|
||||
flavorDimensions += "store"
|
||||
productFlavors {
|
||||
|
||||
@@ -106,8 +106,6 @@ allprojects {
|
||||
// Fix compilation warning for annotations
|
||||
// See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details
|
||||
freeCompilerArgs.add("-Xannotation-default-target=first-only")
|
||||
// Opt-in to context receivers
|
||||
freeCompilerArgs.add("-Xcontext-parameters")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ dependencies {
|
||||
implementation(projects.services.toolbox.api)
|
||||
implementation(libs.androidx.webkit)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.network.retrofit)
|
||||
implementation(libs.serialization.json)
|
||||
implementation(libs.element.call.embedded)
|
||||
api(projects.features.call.api)
|
||||
|
||||
+10
-1
@@ -13,6 +13,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
@@ -36,6 +39,13 @@ fun AddPeopleView(
|
||||
modifier: Modifier = Modifier,
|
||||
invitePeopleView: @Composable () -> Unit,
|
||||
) {
|
||||
val currentOnFinish by rememberUpdatedState(onFinish)
|
||||
LaunchedEffect(state.sendInvitesAction, state.createRoomFromDmAction) {
|
||||
if (state.sendInvitesAction.isSuccess() || state.createRoomFromDmAction.isSuccess()) {
|
||||
currentOnFinish()
|
||||
}
|
||||
}
|
||||
|
||||
HeaderFooterPage(
|
||||
modifier = modifier,
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
@@ -47,7 +57,6 @@ fun AddPeopleView(
|
||||
text = stringResource(CommonStrings.action_finish),
|
||||
onClick = {
|
||||
state.eventSink(InvitePeopleEvents.SendInvites)
|
||||
onFinish()
|
||||
},
|
||||
enabled = state.canInvite,
|
||||
modifier = Modifier
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
<string name="screen_create_room_action_create_room">"Новы пакой"</string>
|
||||
<string name="screen_create_room_add_people_title">"Запрасіць карыстальнікаў"</string>
|
||||
<string name="screen_create_room_error_creating_room">"Пры стварэнні пакоя адбылася памылка"</string>
|
||||
<string name="screen_create_room_name_placeholder">"Дадаць імя…"</string>
|
||||
<string name="screen_create_room_new_room_title">"Новы пакой"</string>
|
||||
<string name="screen_create_room_new_space_title">"Новая прастора"</string>
|
||||
<string name="screen_create_room_private_option_description">"Толькі запрошаныя людзі могуць атрымаць доступ да гэтага пакоя. Усе паведамленні абаронены end-to-end шыфраваннем."</string>
|
||||
<string name="screen_create_room_public_option_description">"Любы можа знайсці гэты пакой.
|
||||
Вы можаце змяніць гэта ў любы час у наладах пакоя."</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Папрасіце далучыцца"</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Адрас"</string>
|
||||
<string name="screen_create_room_space_selection_sheet_title">"Дадаць у прастору"</string>
|
||||
<string name="screen_create_room_topic_label">"Тэма (неабавязкова)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"Дадаць апісанне…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<string name="screen_deactivate_account_list_item_1_bold_part">"Отключить навсегда"</string>
|
||||
<string name="screen_deactivate_account_list_item_2">"Вы будете удалены из всех чатов."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Данные Вашего аккаунта будут удалены с нашего сервера идентификации."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Ваши сообщения по-прежнему будут видны зарегистрированным пользователям, но не будут доступны новым или незарегистрированным пользователям, если вы решите удалить их."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Ваши сообщения по-прежнему будут видны зарегистрированным пользователям, но не будут доступны новым или незарегистрированным пользователям, если Вы решите удалить их."</string>
|
||||
<string name="screen_deactivate_account_title">"Удалить аккаунт"</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="screen_identity_confirmation_title">"Подтвердите личность"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Использовать другое устройство"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Использовать ключ восстановления"</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Теперь вы можете безопасно читать и отправлять сообщения, и все, с кем вы общаетесь в чате, также могут доверять этому устройству."</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Теперь Вы можете безопасно читать и отправлять сообщения, и все, с кем Вы общаетесь в чате, также могут доверять этому устройству."</string>
|
||||
<string name="screen_identity_confirmed_title">"Устройство проверено"</string>
|
||||
<string name="screen_identity_use_another_device">"Использовать другое устройство"</string>
|
||||
<string name="screen_identity_waiting_on_other_device">"Ожидание другого устройства…"</string>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<string name="screen_invites_decline_direct_chat_message">"Вы уверены, что хотите отказаться от личного общения с %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Отклонить чат"</string>
|
||||
<string name="screen_invites_empty_list">"Нет приглашений"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) вас"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) Вас"</string>
|
||||
<string name="screen_migration_message">"Это единоразовая процедура, спасибо, что подождали."</string>
|
||||
<string name="screen_migration_title">"Настройка Вашего аккаунта."</string>
|
||||
<string name="screen_roomlist_a11y_create_message">"Создать новую беседу или комнату"</string>
|
||||
@@ -31,20 +31,20 @@
|
||||
<string name="screen_roomlist_filter_favourites">"Избранные"</string>
|
||||
<string name="screen_roomlist_filter_favourites_empty_state_subtitle">"Добавить чат в избранное можно в настройках чата.
|
||||
На данный момент вы можете убрать фильтры, чтобы увидеть другие ваши чаты."</string>
|
||||
<string name="screen_roomlist_filter_favourites_empty_state_title">"У вас пока нет избранных чатов"</string>
|
||||
<string name="screen_roomlist_filter_favourites_empty_state_title">"У Вас пока нет избранных чатов"</string>
|
||||
<string name="screen_roomlist_filter_invites">"Приглашения"</string>
|
||||
<string name="screen_roomlist_filter_invites_empty_state_title">"У вас нет приглашений."</string>
|
||||
<string name="screen_roomlist_filter_invites_empty_state_title">"У Вас нет приглашений."</string>
|
||||
<string name="screen_roomlist_filter_low_priority">"Низкий приоритет"</string>
|
||||
<string name="screen_roomlist_filter_low_priority_empty_state_title">"У вас пока нет чатов с низким приоритетом."</string>
|
||||
<string name="screen_roomlist_filter_low_priority_empty_state_title">"У Вас пока нет чатов с низким приоритетом."</string>
|
||||
<string name="screen_roomlist_filter_mixed_empty_state_subtitle">"Вы можете убрать фильтры, чтобы увидеть другие ваши чаты."</string>
|
||||
<string name="screen_roomlist_filter_mixed_empty_state_title">"У вас нет чатов, соответствующих фильтрам"</string>
|
||||
<string name="screen_roomlist_filter_mixed_empty_state_title">"У Вас нет чатов, соответствующих фильтрам"</string>
|
||||
<string name="screen_roomlist_filter_people">"Пользователи"</string>
|
||||
<string name="screen_roomlist_filter_people_empty_state_title">"У вас пока нет личных сообщений"</string>
|
||||
<string name="screen_roomlist_filter_people_empty_state_title">"У Вас пока нет личных сообщений"</string>
|
||||
<string name="screen_roomlist_filter_rooms">"Комнаты"</string>
|
||||
<string name="screen_roomlist_filter_rooms_empty_state_title">"Вас пока нет ни в одной комнате"</string>
|
||||
<string name="screen_roomlist_filter_unreads">"Новые"</string>
|
||||
<string name="screen_roomlist_filter_unreads_empty_state_title">"Поздравляем!
|
||||
У вас нет непрочитанных сообщений!"</string>
|
||||
У Вас нет непрочитанных сообщений!"</string>
|
||||
<string name="screen_roomlist_knock_event_sent_description">"Запрос на присоединение отправлен"</string>
|
||||
<string name="screen_roomlist_main_space_title">"Чаты"</string>
|
||||
<string name="screen_roomlist_mark_as_read">"Пометить как прочитанное"</string>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<string name="screen_invites_decline_direct_chat_message">"Вы уверены, что хотите отказаться от личного общения с %1$s?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Отклонить чат"</string>
|
||||
<string name="screen_invites_empty_list">"Нет приглашений"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) вас"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) Вас"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Да, отклонить и заблокировать"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Вы действительно хотите отклонить приглашение в комнату? Также %1$s больше не сможет связаться с вами или приглашать в комнаты."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Отклонить приглашение и заблокировать"</string>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<string name="screen_invite_users_already_a_member">"Уже участник"</string>
|
||||
<string name="screen_invite_users_already_invited">"Уже приглашен(а)"</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_multiple_users">"У тебя пока нет чатов с этими контактами. Подтверди приглашение в эту комнату, прежде чем продолжить."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_one_user">"У вас пока нет чатов с этим контактом. Подтверди приглашение в эту комнату, прежде чем продолжить."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_one_user">"У Вас пока нет чатов с этим контактом. Подтвердите, что это действительно тот контакт, которого Вы хотите пригласить, прежде чем продолжить."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_title_mutiple_users">"Пригласить новых участников в эту комнату?"</string>
|
||||
<string name="screen_invite_users_confirm_dialog_title_one_user">"Пригласить нового участника в эту комнату?"</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Так, адмяніць"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Адхіліць і заблакіраваць"</string>
|
||||
<string name="screen_join_room_join_action">"Далучыцца"</string>
|
||||
<string name="screen_join_room_knock_action">"Націсніце, каб далучыцца"</string>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"%1$s заблокировал(а) вас в комнате."</string>
|
||||
<string name="screen_join_room_ban_by_message">"%1$s заблокировал(а) Вас в комнате."</string>
|
||||
<string name="screen_join_room_ban_message">"Вы были заблокированы в комнате"</string>
|
||||
<string name="screen_join_room_ban_reason">"Причина: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Отменить запрос"</string>
|
||||
@@ -27,7 +27,7 @@
|
||||
<string name="screen_join_room_loading_alert_title">"Не удалось показать предпросмотр комнаты"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s еще не поддерживает пространства. Вы можете получить к ним доступ в веб-версии."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Пространства пока не поддерживаются"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Нажмите кнопку ниже и администратор комнаты получит уведомление. После одобрения вы сможете присоединиться к обсуждению."</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Нажмите кнопку ниже и администратор комнаты получит уведомление. После одобрения Вы сможете присоединиться к беседе."</string>
|
||||
<string name="screen_join_room_subtitle_no_preview">"Вы должны быть участником этой комнаты, чтобы просмотреть историю сообщений."</string>
|
||||
<string name="screen_join_room_title_knock">"Хотите присоединиться к этой комнате?"</string>
|
||||
<string name="screen_join_room_title_no_preview">"Предпросмотр недоступен"</string>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Адхіліць доступ"</string>
|
||||
<string name="screen_room_multiple_knock_requests_view_all_button_title">"Паглядзець усе"</string>
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Прыняць"</string>
|
||||
</resources>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<string name="screen_knock_requests_list_accept_all_alert_description">"Вы действительно хотите принять все заявки на присоединение?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_title">"Принять все запросы"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_button_title">"Принять все"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_description">"Мы не смогли принять все запросы. Попробовать еще раз?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_description">"Мы не смогли принять все запросы. Попробовать ещё раз?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_title">"Не удалось принять все запросы"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_loading_title">"Принять все заявки на присоединение"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_description">"Мы не смогли принять этот запрос. Хотите попробовать еще раз?"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_description">"Мы не смогли принять этот запрос. Хотите попробовать ещё раз?"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_title">"Не удалось принять запрос"</string>
|
||||
<string name="screen_knock_requests_list_accept_loading_title">"Принятие заявки на присоединение"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_confirm_button_title">"Да, отклонить и запретить"</string>
|
||||
@@ -18,7 +18,7 @@
|
||||
<string name="screen_knock_requests_list_decline_alert_description">"Вы уверены, что хотите отклонить запрос %1$s на присоединение к этой комнате?"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Отклонить доступ"</string>
|
||||
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Отклонить и запретить"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_description">"Мы не смогли отклонить этот запрос. Попробовать еще раз?"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_description">"Мы не смогли отклонить этот запрос. Попробовать ещё раз?"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_title">"Не удалось отклонить запрос"</string>
|
||||
<string name="screen_knock_requests_list_decline_loading_title">"Отклонение заявки на присоединение"</string>
|
||||
<string name="screen_knock_requests_list_empty_state_description">"Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="leave_conversation_alert_subtitle">"Вы уверены, что хотите покинуть беседу? Эта беседа не является общедоступной, и вы не сможете присоединиться к ней без приглашения."</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Вы уверены, что хотите покинуть эту комнату? Здесь есть только вы. Если вы покинете комнату, никто не сможет присоединиться к ней в будущем, включая вас."</string>
|
||||
<string name="leave_conversation_alert_subtitle">"Вы уверены, что хотите покинуть беседу? Эта беседа не является общедоступной, и Вы не сможете снова присоединиться к ней без приглашения."</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Вы уверены, что хотите покинуть эту комнату? Здесь есть только Вы. Если Вы покинете комнату, никто не сможет присоединиться к ней в будущем, включая Вас."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Вы уверены, что хотите покинуть эту комнату? Эта комната не является общедоступной, и Вы не сможете присоединиться к ней без приглашения."</string>
|
||||
<string name="leave_room_alert_select_new_owner_action">"Назначить владельцев"</string>
|
||||
<string name="leave_room_alert_select_new_owner_subtitle">"Вы единственный владелец этой комнаты. Перед тем, как её покинуть, необходимо передать владение кому-нибудь другому."</string>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<string name="screen_link_new_device_error_not_supported_title">"QR-код не поддерживается"</string>
|
||||
<string name="screen_link_new_device_error_request_cancelled_subtitle">"Вход на другом устройстве был отменен."</string>
|
||||
<string name="screen_link_new_device_error_request_cancelled_title">"Запрос на вход отменен"</string>
|
||||
<string name="screen_link_new_device_error_request_timeout_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_link_new_device_error_request_timeout_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_link_new_device_error_request_timeout_title">"Вход в систему не был выполнен вовремя"</string>
|
||||
<string name="screen_link_new_device_mobile_step1">"Откройте %1$s на другом устройстве"</string>
|
||||
<string name="screen_link_new_device_mobile_step2">"Выберите %1$s"</string>
|
||||
@@ -26,7 +26,7 @@
|
||||
<string name="screen_link_new_device_root_loading_qr_code">"Загрузка QR-кода…"</string>
|
||||
<string name="screen_link_new_device_root_mobile_device">"Смартфон"</string>
|
||||
<string name="screen_link_new_device_root_title">"Какое устройство вы хотите привязать?"</string>
|
||||
<string name="screen_link_new_device_wrong_number_subtitle">"Пожалуйста, попробуйте еще раз и убедитесь, что вы правильно ввели 2-значный код. Если цифры по-прежнему не совпадают, обратитесь к администратору сервера."</string>
|
||||
<string name="screen_link_new_device_wrong_number_subtitle">"Пожалуйста, попробуйте ещё раз и убедитесь, что Вы правильно ввели 2-значный код. Если цифры по-прежнему не совпадают, обратитесь к администратору сервера."</string>
|
||||
<string name="screen_link_new_device_wrong_number_title">"Цифры не совпадают"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_description">"Не удалось установить безопасное соединение с новым устройством. Не беспокойтесь, существующие устройства в безопасности."</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_header">"Что теперь?"</string>
|
||||
@@ -40,9 +40,9 @@
|
||||
<string name="screen_qr_code_login_error_cancelled_title">"Запрос на вход отменен"</string>
|
||||
<string name="screen_qr_code_login_error_declined_subtitle">"Вход в систему был отклонен на другом устройстве."</string>
|
||||
<string name="screen_qr_code_login_error_declined_title">"Вход отклонен"</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_subtitle">"На этом все."</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_subtitle">"На этом всё."</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_title">"Вход уже выполнен на другом устройстве"</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_qr_code_login_error_expired_title">"Вход в систему не был выполнен вовремя"</string>
|
||||
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Другое устройство не поддерживает вход в %s с помощью QR-кода.
|
||||
|
||||
@@ -55,6 +55,6 @@
|
||||
<string name="screen_qr_code_login_invalid_scan_state_subtitle">"Неверный QR-код"</string>
|
||||
<string name="screen_qr_code_login_no_camera_permission_state_description">"Чтобы продолжить, вам необходимо разрешить %1$s использовать камеру вашего устройства."</string>
|
||||
<string name="screen_qr_code_login_no_camera_permission_state_title">"Разрешите доступ к камере для сканирования QR-кода"</string>
|
||||
<string name="screen_qr_code_login_unknown_error_description">"Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_qr_code_login_unknown_error_description">"Произошла непредвиденная ошибка. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_qr_code_login_verify_code_loading">"Ожидание другого устройства"</string>
|
||||
</resources>
|
||||
|
||||
+45
-25
@@ -8,6 +8,7 @@
|
||||
|
||||
package io.element.android.features.location.api
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
@@ -24,13 +25,17 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.createBitmap
|
||||
import coil3.Extras
|
||||
import coil3.asImage
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.SuccessResult
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.location.api.internal.StaticMapPlaceholder
|
||||
import io.element.android.features.location.api.internal.StaticMapUrlBuilder
|
||||
@@ -39,6 +44,7 @@ import io.element.android.libraries.designsystem.components.LocationPin
|
||||
import io.element.android.libraries.designsystem.components.PinVariant
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
/**
|
||||
* Shows a static map image downloaded via a third party service's static maps API.
|
||||
@@ -128,32 +134,46 @@ private fun BoxWithConstraintsScope.LoadableMapContent(
|
||||
var retryHash by remember { mutableIntStateOf(0) }
|
||||
val builder = remember { StaticMapUrlBuilder() }
|
||||
|
||||
val painter = rememberAsyncImagePainter(
|
||||
model = if (constraints.isZero) {
|
||||
// Avoid building a URL if any of the size constraints is zero
|
||||
null
|
||||
} else {
|
||||
ImageRequest.Builder(context)
|
||||
.data(
|
||||
builder.build(
|
||||
lat = location.lat,
|
||||
lon = location.lon,
|
||||
zoom = zoom,
|
||||
darkMode = darkMode,
|
||||
width = constraints.maxWidth,
|
||||
height = constraints.maxHeight,
|
||||
density = LocalDensity.current.density,
|
||||
val (painter, state, contentScale) = if (LocalInspectionMode.current) {
|
||||
val painter = painterResource(CommonDrawables.sample_map)
|
||||
val state = AsyncImagePainter.State.Success(
|
||||
painter = painter,
|
||||
result = SuccessResult(
|
||||
image = createBitmap(1, 1, Bitmap.Config.ALPHA_8).asImage(),
|
||||
request = ImageRequest.Builder(context).build()
|
||||
)
|
||||
)
|
||||
Triple(painter, state, ContentScale.Crop)
|
||||
} else {
|
||||
val painter = rememberAsyncImagePainter(
|
||||
model = if (constraints.isZero) {
|
||||
// Avoid building a URL if any of the size constraints is zero
|
||||
null
|
||||
} else {
|
||||
ImageRequest.Builder(context)
|
||||
.data(
|
||||
builder.build(
|
||||
lat = location.lat,
|
||||
lon = location.lon,
|
||||
zoom = zoom,
|
||||
darkMode = darkMode,
|
||||
width = constraints.maxWidth,
|
||||
height = constraints.maxHeight,
|
||||
density = LocalDensity.current.density,
|
||||
)
|
||||
)
|
||||
)
|
||||
.size(width = constraints.maxWidth, height = constraints.maxHeight)
|
||||
.apply {
|
||||
extras.set(Extras.Key("retry_hash"), retryHash).build()
|
||||
}
|
||||
.build()
|
||||
}
|
||||
)
|
||||
.size(width = constraints.maxWidth, height = constraints.maxHeight)
|
||||
.apply {
|
||||
extras.set(Extras.Key("retry_hash"), retryHash).build()
|
||||
}
|
||||
.build()
|
||||
}
|
||||
)
|
||||
|
||||
val state by painter.state.collectAsState()
|
||||
Triple(painter, state, ContentScale.Fit)
|
||||
}
|
||||
|
||||
val state by painter.state.collectAsState()
|
||||
when (state) {
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
Image(
|
||||
@@ -162,7 +182,7 @@ private fun BoxWithConstraintsScope.LoadableMapContent(
|
||||
modifier = Modifier.size(width = maxWidth, height = maxHeight),
|
||||
// The returned image can be smaller than the requested size due to the static maps API having
|
||||
// a max width and height of 2048 px. We apply ContentScale.Fit to handle this.
|
||||
contentScale = ContentScale.Fit,
|
||||
contentScale = contentScale,
|
||||
)
|
||||
LocationPin(variant = pinVariant, modifier = Modifier.centerBottomEdge(this))
|
||||
}
|
||||
|
||||
+3
@@ -14,6 +14,7 @@ import io.element.android.features.location.impl.common.ui.LocationConstraintsDi
|
||||
sealed interface LocationConstraintsCheck {
|
||||
data object Success : LocationConstraintsCheck
|
||||
data object PermissionRationale : LocationConstraintsCheck
|
||||
data object PermissionShouldBeRequested : LocationConstraintsCheck
|
||||
data object PermissionDenied : LocationConstraintsCheck
|
||||
data object LocationServiceDisabled : LocationConstraintsCheck
|
||||
data object NotEnoughPowerLevel : LocationConstraintsCheck
|
||||
@@ -34,6 +35,7 @@ fun checkLocationConstraints(
|
||||
}
|
||||
}
|
||||
permissionsState.shouldShowRationale -> LocationConstraintsCheck.PermissionRationale
|
||||
!permissionsState.permissionsAlreadyRequested -> LocationConstraintsCheck.PermissionShouldBeRequested
|
||||
else -> LocationConstraintsCheck.PermissionDenied
|
||||
}
|
||||
}
|
||||
@@ -41,6 +43,7 @@ fun checkLocationConstraints(
|
||||
fun LocationConstraintsCheck.toDialogState(): LocationConstraintsDialogState {
|
||||
return when (this) {
|
||||
LocationConstraintsCheck.Success -> LocationConstraintsDialogState.None
|
||||
LocationConstraintsCheck.PermissionShouldBeRequested -> LocationConstraintsDialogState.None
|
||||
LocationConstraintsCheck.PermissionRationale -> LocationConstraintsDialogState.PermissionRationale
|
||||
LocationConstraintsCheck.PermissionDenied -> LocationConstraintsDialogState.PermissionDenied
|
||||
LocationConstraintsCheck.LocationServiceDisabled -> LocationConstraintsDialogState.LocationServiceDisabled
|
||||
|
||||
+12
-2
@@ -9,6 +9,10 @@
|
||||
package io.element.android.features.location.impl.common.permissions
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
@@ -32,11 +36,16 @@ class DefaultPermissionsPresenter(
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
override fun present(): PermissionsState {
|
||||
val multiplePermissionsState = rememberMultiplePermissionsState(permissions = permissions)
|
||||
var permissionsRequested by remember { mutableStateOf(false) }
|
||||
val multiplePermissionsState = rememberMultiplePermissionsState(permissions = permissions) {
|
||||
permissionsRequested = true
|
||||
}
|
||||
|
||||
fun handleEvent(event: PermissionsEvents) {
|
||||
when (event) {
|
||||
PermissionsEvents.RequestPermissions -> multiplePermissionsState.launchMultiplePermissionRequest()
|
||||
PermissionsEvents.RequestPermissions -> {
|
||||
multiplePermissionsState.launchMultiplePermissionRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +56,7 @@ class DefaultPermissionsPresenter(
|
||||
else -> PermissionsState.Permissions.NoneGranted
|
||||
},
|
||||
shouldShowRationale = multiplePermissionsState.shouldShowRationale,
|
||||
permissionsAlreadyRequested = permissionsRequested,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
}
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ package io.element.android.features.location.impl.common.permissions
|
||||
data class PermissionsState(
|
||||
val permissions: Permissions,
|
||||
val shouldShowRationale: Boolean,
|
||||
val permissionsAlreadyRequested: Boolean,
|
||||
val eventSink: (PermissionsEvents) -> Unit,
|
||||
) {
|
||||
sealed interface Permissions {
|
||||
|
||||
+46
-18
@@ -88,6 +88,8 @@ class ShareLocationPresenter(
|
||||
var dialogState: ShareLocationState.Dialog by remember {
|
||||
mutableStateOf(ShareLocationState.Dialog.None)
|
||||
}
|
||||
// true when trying to initiate the live location share
|
||||
var pendingLiveLocationShare by remember { mutableStateOf(false) }
|
||||
val startLiveLocationAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||
val currentUser by client.userProfile.collectAsState()
|
||||
val customMapStyleUrl by produceState(AsyncData.Loading()) {
|
||||
@@ -100,34 +102,55 @@ class ShareLocationPresenter(
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
fun checkLocationConstraints() {
|
||||
// No need to check SendLiveLocationPermissions here
|
||||
val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED)
|
||||
val locationConstraints = checkLocationConstraints(
|
||||
permissionsState = permissionsState,
|
||||
locationActions = locationActions,
|
||||
// No need to check SendLiveLocationPermissions here
|
||||
sendLiveLocationPermissions = SendLiveLocationPermissions.GRANTED
|
||||
)
|
||||
if (locationConstraints is LocationConstraintsCheck.PermissionShouldBeRequested) {
|
||||
permissionsState.eventSink(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
trackUserPosition = locationConstraints is LocationConstraintsCheck.Success
|
||||
dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState())
|
||||
}
|
||||
|
||||
suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog {
|
||||
val hasAcceptedDisclaimer = liveLocationStore.hasAcceptedLiveLocationDisclaimer()
|
||||
val constraintsResult = checkLocationConstraints(permissionsState, locationActions, sendLiveLocationPermissions)
|
||||
return when {
|
||||
!hasAcceptedDisclaimer -> {
|
||||
ShareLocationState.Dialog.LiveLocationDisclaimer
|
||||
}
|
||||
constraintsResult is LocationConstraintsCheck.Success -> {
|
||||
val durations = LIVE_LOCATION_DURATIONS.map {
|
||||
LiveLocationDuration(duration = it, formatted = durationFormatter.format(it))
|
||||
suspend fun checkLiveLocationConstraints() {
|
||||
val locationConstraints = checkLocationConstraints(
|
||||
permissionsState = permissionsState,
|
||||
locationActions = locationActions,
|
||||
sendLiveLocationPermissions = sendLiveLocationPermissions,
|
||||
)
|
||||
when (locationConstraints) {
|
||||
LocationConstraintsCheck.Success -> {
|
||||
val hasAcceptedDisclaimer = liveLocationStore.hasAcceptedLiveLocationDisclaimer()
|
||||
dialogState = if (!hasAcceptedDisclaimer) {
|
||||
ShareLocationState.Dialog.LiveLocationDisclaimer
|
||||
} else {
|
||||
val durations = LIVE_LOCATION_DURATIONS.map {
|
||||
LiveLocationDuration(duration = it, formatted = durationFormatter.format(it))
|
||||
}
|
||||
ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList())
|
||||
}
|
||||
ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList())
|
||||
}
|
||||
else -> {
|
||||
ShareLocationState.Dialog.Constraints(constraintsResult.toDialogState())
|
||||
if (locationConstraints is LocationConstraintsCheck.PermissionShouldBeRequested) {
|
||||
permissionsState.eventSink(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val userLocationState = userLocationStateFactory.create(permissionsState.isAnyGranted)
|
||||
|
||||
LaunchedEffect(permissionsState.permissions) { checkLocationConstraints() }
|
||||
LaunchedEffect(permissionsState) {
|
||||
if (pendingLiveLocationShare) {
|
||||
checkLiveLocationConstraints()
|
||||
} else {
|
||||
checkLocationConstraints()
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvent(event: ShareLocationEvent) {
|
||||
when (event) {
|
||||
@@ -136,7 +159,10 @@ class ShareLocationPresenter(
|
||||
}
|
||||
ShareLocationEvent.StartTrackingUserLocation -> checkLocationConstraints()
|
||||
ShareLocationEvent.StopTrackingUserLocation -> trackUserPosition = false
|
||||
ShareLocationEvent.DismissDialog -> dialogState = ShareLocationState.Dialog.None
|
||||
ShareLocationEvent.DismissDialog -> {
|
||||
pendingLiveLocationShare = false
|
||||
dialogState = ShareLocationState.Dialog.None
|
||||
}
|
||||
ShareLocationEvent.OpenAppSettings -> {
|
||||
locationActions.openAppSettings()
|
||||
dialogState = ShareLocationState.Dialog.None
|
||||
@@ -146,15 +172,17 @@ class ShareLocationPresenter(
|
||||
dialogState = ShareLocationState.Dialog.None
|
||||
}
|
||||
ShareLocationEvent.InitiateLiveLocationShare -> scope.launch {
|
||||
dialogState = computeLiveLocationDialogState()
|
||||
pendingLiveLocationShare = true
|
||||
checkLiveLocationConstraints()
|
||||
}
|
||||
ShareLocationEvent.AcceptLiveLocationDisclaimer -> scope.launch {
|
||||
liveLocationStore.setAcceptedLiveLocationDisclaimer()
|
||||
.onSuccess {
|
||||
dialogState = computeLiveLocationDialogState()
|
||||
checkLiveLocationConstraints()
|
||||
}
|
||||
}
|
||||
is ShareLocationEvent.StartLiveLocationShare -> scope.launch {
|
||||
pendingLiveLocationShare = false
|
||||
dialogState = ShareLocationState.Dialog.None
|
||||
startLiveLocationAction.runUpdatingState {
|
||||
liveLocationShareManager.startShare(
|
||||
|
||||
+16
-6
@@ -90,10 +90,22 @@ import kotlinx.coroutines.launch
|
||||
value = AsyncData.Success(client.getMapStyleUrl().getOrNull())
|
||||
}
|
||||
|
||||
LaunchedEffect(permissionsState.permissions) {
|
||||
if (permissionsState.isAnyGranted) {
|
||||
dialogState = LocationConstraintsDialogState.None
|
||||
fun checkLocationConstraints() {
|
||||
val locationConstraints = checkLocationConstraints(
|
||||
permissionsState = permissionsState,
|
||||
locationActions = locationActions,
|
||||
// No need to check SendLiveLocationPermissions here
|
||||
sendLiveLocationPermissions = SendLiveLocationPermissions.GRANTED
|
||||
)
|
||||
if (locationConstraints is LocationConstraintsCheck.PermissionShouldBeRequested) {
|
||||
permissionsState.eventSink(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
isTrackMyLocation = locationConstraints is LocationConstraintsCheck.Success
|
||||
dialogState = locationConstraints.toDialogState()
|
||||
}
|
||||
|
||||
LaunchedEffect(permissionsState) {
|
||||
checkLocationConstraints()
|
||||
}
|
||||
|
||||
fun handleEvent(event: ShowLocationEvent) {
|
||||
@@ -103,9 +115,7 @@ import kotlinx.coroutines.launch
|
||||
}
|
||||
is ShowLocationEvent.TrackMyLocation -> {
|
||||
if (event.enabled) {
|
||||
val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED)
|
||||
isTrackMyLocation = locationConstraints is LocationConstraintsCheck.Success
|
||||
dialogState = locationConstraints.toDialogState()
|
||||
checkLocationConstraints()
|
||||
} else {
|
||||
isTrackMyLocation = false
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_share_location_live_location_disclaimer_title">"Ваша історія поточного місцезнаходження зберігатиметься у кімнаті та буде доступна учасникам після завершення сеансу."</string>
|
||||
<string name="screen_share_location_live_location_duration_picker_title">"Виберіть, як довго ділитися своїм місцезнаходженням."</string>
|
||||
<string name="screen_share_location_live_location_missing_permissions">"У вас немає дозволу ділитися своїм місцезнаходженням у реальному часі в цій кімнаті"</string>
|
||||
</resources>
|
||||
|
||||
+2
@@ -13,10 +13,12 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS
|
||||
fun aPermissionsState(
|
||||
permissions: PermissionsState.Permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale: Boolean = false,
|
||||
permissionsRequested: Boolean = false,
|
||||
): PermissionsState {
|
||||
return PermissionsState(
|
||||
permissions = permissions,
|
||||
shouldShowRationale = shouldShowRationale,
|
||||
permissionsAlreadyRequested = permissionsRequested,
|
||||
eventSink = {},
|
||||
)
|
||||
}
|
||||
|
||||
+16
-1
@@ -64,10 +64,25 @@ class LocationConstraintsCheckTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkLocationConstraints returns PermissionDenied when permissions denied without rationale`() {
|
||||
fun `checkLocationConstraints returns PermissionShouldBeRequested when permissions not yet requested`() {
|
||||
val permissionsState = aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = false,
|
||||
)
|
||||
val locationActions = FakeLocationActions(isLocationEnabled = true)
|
||||
|
||||
val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED)
|
||||
|
||||
assertThat(result).isEqualTo(LocationConstraintsCheck.PermissionShouldBeRequested)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkLocationConstraints returns PermissionDenied when permissions already requested and denied without rationale`() {
|
||||
val permissionsState = aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
val locationActions = FakeLocationActions(isLocationEnabled = true)
|
||||
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ class FakePermissionsPresenter : PermissionsPresenter {
|
||||
private var state = PermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsAlreadyRequested = false,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
set(value) {
|
||||
|
||||
+34
-3
@@ -160,6 +160,24 @@ class ShareLocationPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial state with permissions not yet requested triggers permission request`() = runTest {
|
||||
val shareLocationPresenter = createShareLocationPresenter()
|
||||
fakePermissionsPresenter.givenState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = false,
|
||||
)
|
||||
)
|
||||
|
||||
shareLocationPresenter.test {
|
||||
skipItems(2)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
assertThat(fakePermissionsPresenter.events).contains(PermissionsEvents.RequestPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial state with permissions denied`() = runTest {
|
||||
val shareLocationPresenter = createShareLocationPresenter()
|
||||
@@ -167,6 +185,7 @@ class ShareLocationPresenterTest {
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -291,6 +310,7 @@ class ShareLocationPresenterTest {
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -359,7 +379,12 @@ class ShareLocationPresenterTest {
|
||||
|
||||
@Test
|
||||
fun `ShowLiveLocationDurationPicker shows disclaimer when acceptance is missing`() = runTest {
|
||||
val presenter = createShareLocationPresenter()
|
||||
val room = FakeJoinedRoom(
|
||||
baseRoom = FakeBaseRoom(
|
||||
roomPermissions = grantedSendLiveLocationPermissions()
|
||||
)
|
||||
)
|
||||
val presenter = createShareLocationPresenter(joinedRoom = room)
|
||||
fakePermissionsPresenter.givenState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.AllGranted,
|
||||
@@ -462,7 +487,12 @@ class ShareLocationPresenterTest {
|
||||
|
||||
@Test
|
||||
fun `ShowLiveLocationDurationPicker uses the active session disclaimer state`() = runTest {
|
||||
val joinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(sessionId = SessionId("@alice:server")))
|
||||
val joinedRoom = FakeJoinedRoom(
|
||||
baseRoom = FakeBaseRoom(
|
||||
sessionId = SessionId("@alice:server"),
|
||||
roomPermissions = grantedSendLiveLocationPermissions()
|
||||
),
|
||||
)
|
||||
createLiveLocationStore(sessionId = SessionId("@bob:server"))
|
||||
.setAcceptedLiveLocationDisclaimer()
|
||||
.getOrThrow()
|
||||
@@ -505,12 +535,13 @@ class ShareLocationPresenterTest {
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
)
|
||||
|
||||
shareLocationPresenter.test {
|
||||
val initialState = awaitFirstItem()
|
||||
// Dismiss initial dialog
|
||||
// Dismiss initial dialog to allow re-triggering it
|
||||
initialState.eventSink(ShareLocationEvent.DismissDialog)
|
||||
val dismissedState = awaitItem()
|
||||
|
||||
|
||||
+25
-6
@@ -37,7 +37,6 @@ import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.test
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
@@ -103,8 +102,8 @@ class ShowLocationPresenterTest {
|
||||
|
||||
val presenter = createShowLocationPresenter()
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
assertThat(awaitItem().isTrackMyLocation).isFalse()
|
||||
assertThat(awaitItem().isTrackMyLocation).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,15 +128,12 @@ class ShowLocationPresenterTest {
|
||||
)
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isTrackMyLocation).isFalse()
|
||||
|
||||
initialState.eventSink(ShowLocationEvent.TrackMyLocation(true))
|
||||
val trackMyLocationState = awaitItem()
|
||||
|
||||
delay(1)
|
||||
|
||||
assertThat(trackMyLocationState.isTrackMyLocation).isTrue()
|
||||
|
||||
// Swipe the map to switch mode
|
||||
@@ -201,12 +197,34 @@ class ShowLocationPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `TrackMyLocation with permissions not yet requested triggers permission request`() = runTest {
|
||||
fakePermissionsPresenter.givenState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = false,
|
||||
)
|
||||
)
|
||||
|
||||
val presenter = createShowLocationPresenter()
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.eventSink(ShowLocationEvent.TrackMyLocation(true))
|
||||
|
||||
assertThat(fakePermissionsPresenter.events).contains(PermissionsEvents.RequestPermissions)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `permission denied dialog dismiss`() = runTest {
|
||||
fakePermissionsPresenter.givenState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -235,6 +253,7 @@ class ShowLocationPresenterTest {
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
permissionsRequested = true,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
</plurals>
|
||||
<string name="screen_app_lock_use_biometric_android">"Выкарыстоўваць біяметрыю"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"Выкарыстоўваць PIN-код"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выхад…"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выдаленне прылады…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"Используйте %1$s для разблокировки приложения"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"Выберите PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"Подтвердите PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Установите блокировку на %1$s, чтобы повысить безопасность ваших чатов.
|
||||
<string name="screen_app_lock_setup_pin_context">"Установите блокировку на %1$s, чтобы повысить безопасность Ваших чатов.
|
||||
|
||||
Выберите код, который трудно забыть. Если вы забудете PIN-код, вам придется выйти из приложения."</string>
|
||||
Выберите код, который трудно забыть. Если Вы забудете PIN-код, Вам придется выйти из аккаунта."</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_content">"Этот PIN-код небезопасен."</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_title">"Выбрать другой PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Повторите PIN-код"</string>
|
||||
@@ -25,14 +25,14 @@
|
||||
<string name="screen_app_lock_signout_alert_message">"Чтобы продолжить, вам необходимо повторно войти в систему и создать новый PIN-код"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Это устройство удаляется"</string>
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"У вас осталась %1$d попытка разблокировки"</item>
|
||||
<item quantity="few">"У вас остались %1$d попытки разблокировки"</item>
|
||||
<item quantity="many">"У вас осталось %1$d попыток разблокировки"</item>
|
||||
<item quantity="one">"У Вас осталась %1$d попытка разблокировки"</item>
|
||||
<item quantity="few">"У Вас остались %1$d попытки разблокировки"</item>
|
||||
<item quantity="many">"У Вас осталось %1$d попыток разблокировки"</item>
|
||||
</plurals>
|
||||
<plurals name="screen_app_lock_subtitle_wrong_pin">
|
||||
<item quantity="one">"Неверный PIN-код. У вас осталась %1$d попытка"</item>
|
||||
<item quantity="few">"Неверный PIN-код. У вас остались %1$d попытки"</item>
|
||||
<item quantity="many">"Неверный PIN-код. У вас осталось %1$d попыток"</item>
|
||||
<item quantity="one">"Неверный PIN-код. У Вас осталась %1$d попытка"</item>
|
||||
<item quantity="few">"Неверный PIN-код. У Вас остались %1$d попытки"</item>
|
||||
<item quantity="many">"Неверный PIN-код. У Вас осталось %1$d попыток"</item>
|
||||
</plurals>
|
||||
<string name="screen_app_lock_use_biometric_android">"Использовать биометрию"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"Использовать PIN-код"</string>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<string name="screen_change_server_subtitle">"Які адрас вашага сервера?"</string>
|
||||
<string name="screen_change_server_title">"Выберыце свой сервер"</string>
|
||||
<string name="screen_create_account_title">"Стварыць уліковы запіс"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Гэты ўліковы запіс быў дэактываваны."</string>
|
||||
<string name="screen_login_error_deactivated_account">"Гэты ўліковы запіс быў выдалены."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Няправільнае імя карыстальніка і/або пароль"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Гэта несапраўдны ідэнтыфікатар карыстальніка. Чаканы фармат: ‘@user:homeserver.org’"</string>
|
||||
<string name="screen_login_error_refresh_tokens">"Гэты сервер настроены на выкарыстанне маркераў абнаўлення. Яны не падтрымліваюцца пры ўваходзе на аснове пароля."</string>
|
||||
@@ -29,6 +29,7 @@
|
||||
<string name="screen_login_subtitle">"Matrix - гэта адкрытая сетка для бяспечнай, дэцэнтралізаванай сувязі."</string>
|
||||
<string name="screen_login_title">"Сардэчна запрашаем!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"Увайсці ў %1$s"</string>
|
||||
<string name="screen_onboarding_app_version">"Версія %1$s"</string>
|
||||
<string name="screen_onboarding_sign_in_manually">"Увайсці ўручную"</string>
|
||||
<string name="screen_onboarding_sign_in_to">"Увайсці ў %1$s"</string>
|
||||
<string name="screen_onboarding_sign_in_with_qr_code">"Увайсці з QR-кодам"</string>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<string name="screen_login_error_unsupported_authentication">"Выбранный сервер не поддерживает вход по паролю и OAuth. Пожалуйста, свяжитесь с администратором или выберите другой сервер."</string>
|
||||
<string name="screen_login_form_header">"Введите свои данные"</string>
|
||||
<string name="screen_login_subtitle">"Matrix — это открытая сеть для безопасной децентрализованной связи."</string>
|
||||
<string name="screen_login_title">"Рады видеть вас снова!"</string>
|
||||
<string name="screen_login_title">"Рады видеть Вас снова!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"Войти в %1$s"</string>
|
||||
<string name="screen_missing_key_backup_open_element_classic">"Открыть Element Classic"</string>
|
||||
<string name="screen_missing_key_backup_step_1">"Откройте Element Classic на своем устройстве."</string>
|
||||
@@ -69,9 +69,9 @@
|
||||
<string name="screen_qr_code_login_error_cancelled_title">"Запрос на вход отменен"</string>
|
||||
<string name="screen_qr_code_login_error_declined_subtitle">"Вход в систему был отклонен на другом устройстве."</string>
|
||||
<string name="screen_qr_code_login_error_declined_title">"Вход отклонен"</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_subtitle">"На этом все."</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_subtitle">"На этом всё."</string>
|
||||
<string name="screen_qr_code_login_error_device_already_signed_in_title">"Вход уже выполнен на другом устройстве"</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"Срок действия входа истек. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_qr_code_login_error_expired_title">"Вход в систему не был выполнен вовремя"</string>
|
||||
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Другое устройство не поддерживает вход в %s с помощью QR-кода.
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
<string name="screen_qr_code_login_no_camera_permission_state_title">"Разрешите доступ к камере для сканирования QR-кода"</string>
|
||||
<string name="screen_qr_code_login_scanning_state_title">"Сканировать QR-код"</string>
|
||||
<string name="screen_qr_code_login_start_over_button">"Начать заново"</string>
|
||||
<string name="screen_qr_code_login_unknown_error_description">"Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_qr_code_login_unknown_error_description">"Произошла непредвиденная ошибка. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_qr_code_login_verify_code_loading">"Ожидание другого устройства"</string>
|
||||
<string name="screen_qr_code_login_verify_code_subtitle">"Сервер для аккаунта может запросить следующий код для подтверждения входа."</string>
|
||||
<string name="screen_qr_code_login_verify_code_title">"Ваш код подтверждения"</string>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_signout_confirmation_dialog_content">"Вы ўпэўнены, што хочаце выйсці?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_content">"Вы ўпэўненыя, што хочаце выдаліць гэту прыладу?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Выйсці"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Выйсці"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выхад…"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выдаленне прылады…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Вы збіраецеся выйсці з апошняга сеанса. Калі вы выйдзеце з сістэмы зараз, вы страціце доступ да зашыфраваных паведамленняў."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Вы адключылі рэзервовае капіраванне"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Вашы ключы ўсё яшчэ захоўваліся, калі вы выйшлі з сеткі. Паўторна падключыцеся, каб можна было стварыць рэзервовую копію вашых ключоў перад выхадам."</string>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Это ваше единственное устройство. Если вы его удалите, вам потребуется ключ восстановления, чтобы подтвердить свою цифровую личность и восстановить зашифрованные чаты при следующем входе в систему."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Вы потеряете доступ к своим зашифрованным чатам"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Когда вы отключились от сети, резервное копирование ваших ключей продолжалось. Подключитесь снова, чтобы резервная копия ваших ключей была создана, прежде чем вы отключите это устройство."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Резервное копирование ключей все еще продолжается"</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Резервное копирование ключей всё ещё продолжается"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Пожалуйста, дождитесь завершения процесса, прежде чем выходить из системы."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Резервное копирование ключей все еще продолжается"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Резервное копирование ключей всё ещё продолжается"</string>
|
||||
<string name="screen_signout_preference_item">"Удалить это устройство"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Это ваше единственное устройство. Если вы его удалите, вам потребуется ключ восстановления, чтобы подтвердить свою цифровую личность и восстановить зашифрованные чаты при следующем входе в систему."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Вы потеряете доступ к своим зашифрованным чатам"</string>
|
||||
|
||||
+36
@@ -190,6 +190,9 @@ class MessagesFlowNode(
|
||||
|
||||
@Parcelize
|
||||
data object ThreadsList : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class AvatarPreview(val name: String, val avatarUrl: String) : NavTarget
|
||||
}
|
||||
|
||||
private val callback: MessagesEntryPoint.Callback = callback()
|
||||
@@ -327,6 +330,10 @@ class MessagesFlowNode(
|
||||
override fun navigateToDeveloperSettings() {
|
||||
callback.navigateToDeveloperSettings()
|
||||
}
|
||||
|
||||
override fun navigateToAvatarPreview(username: String, avatarUrl: String) {
|
||||
overlay.show(NavTarget.AvatarPreview(username, avatarUrl))
|
||||
}
|
||||
}
|
||||
val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId)
|
||||
createNode<MessagesNode>(buildContext, listOf(callback, inputs))
|
||||
@@ -562,6 +569,10 @@ class MessagesFlowNode(
|
||||
override fun navigateToDeveloperSettings() {
|
||||
callback.navigateToDeveloperSettings()
|
||||
}
|
||||
|
||||
override fun navigateToAvatarPreview(username: String, avatarUrl: String) {
|
||||
overlay.show(NavTarget.AvatarPreview(username, avatarUrl))
|
||||
}
|
||||
}
|
||||
createNode<ThreadedMessagesNode>(buildContext, listOf(inputs, callback))
|
||||
}
|
||||
@@ -573,6 +584,31 @@ class MessagesFlowNode(
|
||||
}
|
||||
createNode<ThreadsListNode>(buildContext, listOf(callback))
|
||||
}
|
||||
is NavTarget.AvatarPreview -> {
|
||||
val callback = object : MediaViewerEntryPoint.Callback {
|
||||
override fun onDone() {
|
||||
overlay.hide()
|
||||
}
|
||||
|
||||
override fun viewInTimeline(eventId: EventId) {
|
||||
// Cannot happen
|
||||
}
|
||||
|
||||
override fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) {
|
||||
// Cannot happen
|
||||
}
|
||||
}
|
||||
val params = mediaViewerEntryPoint.createParamsForAvatar(
|
||||
filename = navTarget.name,
|
||||
avatarUrl = navTarget.avatarUrl,
|
||||
)
|
||||
mediaViewerEntryPoint.createNode(
|
||||
parentNode = this,
|
||||
buildContext = buildContext,
|
||||
params = params,
|
||||
callback = callback,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -66,6 +66,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.alias.matches
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
import io.element.android.libraries.mediaplayer.api.MediaPlayer
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard
|
||||
@@ -107,7 +108,7 @@ class MessagesNode(
|
||||
private val timelineController = TimelineController(room, room.liveTimeline)
|
||||
private val presenter = presenterFactory.create(
|
||||
navigator = this,
|
||||
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false),
|
||||
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = null),
|
||||
timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this),
|
||||
actionListPresenter = actionListPresenterFactory.create(
|
||||
postProcessor = TimelineItemActionPostProcessor.Default,
|
||||
@@ -136,6 +137,8 @@ class MessagesNode(
|
||||
fun navigateToDeveloperSettings()
|
||||
|
||||
fun navigateToThreadsList()
|
||||
|
||||
fun navigateToAvatarPreview(username: String, avatarUrl: String)
|
||||
}
|
||||
|
||||
override fun onBuilt() {
|
||||
@@ -319,6 +322,11 @@ class MessagesNode(
|
||||
else -> state.roomMemberModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target))
|
||||
}
|
||||
},
|
||||
onAvatarClick = { user ->
|
||||
user.avatarUrl?.let { url ->
|
||||
callback.navigateToAvatarPreview(user.getBestName(), url)
|
||||
}
|
||||
},
|
||||
modifier = Modifier,
|
||||
)
|
||||
|
||||
|
||||
+7
-8
@@ -49,6 +49,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
||||
@@ -109,7 +110,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
|
||||
class MessageComposerPresenter(
|
||||
@Assisted private val navigator: MessagesNavigator,
|
||||
@Assisted private val timelineController: TimelineController,
|
||||
@Assisted private val isInThread: Boolean,
|
||||
@Assisted private val threadRoot: ThreadId?,
|
||||
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
|
||||
private val room: JoinedRoom,
|
||||
private val mediaPickerProvider: PickerProvider,
|
||||
@@ -138,10 +139,11 @@ class MessageComposerPresenter(
|
||||
fun create(
|
||||
timelineController: TimelineController,
|
||||
navigator: MessagesNavigator,
|
||||
isInThread: Boolean,
|
||||
threadRoot: ThreadId?,
|
||||
): MessageComposerPresenter
|
||||
}
|
||||
|
||||
private val isInThread = threadRoot != null
|
||||
private val mediaSender = mediaSenderFactory.create(timelineMode = timelineController.mainTimelineMode())
|
||||
|
||||
private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA)
|
||||
@@ -234,8 +236,7 @@ class MessageComposerPresenter(
|
||||
LaunchedEffect(Unit) {
|
||||
val draft = draftService.loadDraft(
|
||||
roomId = room.roomId,
|
||||
// TODO support threads in composer
|
||||
threadRoot = null,
|
||||
threadRoot = threadRoot,
|
||||
isVolatile = false
|
||||
)
|
||||
if (draft != null) {
|
||||
@@ -652,8 +653,7 @@ class MessageComposerPresenter(
|
||||
roomId = room.roomId,
|
||||
draft = draft,
|
||||
isVolatile = isVolatile,
|
||||
// TODO support threads in composer
|
||||
threadRoot = null,
|
||||
threadRoot = threadRoot,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -816,8 +816,7 @@ class MessageComposerPresenter(
|
||||
// Use the volatile draft only when coming from edit mode otherwise.
|
||||
val draft = draftService.loadDraft(
|
||||
roomId = room.roomId,
|
||||
// TODO support threads in composer
|
||||
threadRoot = null,
|
||||
threadRoot = threadRoot,
|
||||
isVolatile = true
|
||||
).takeIf { fromEdit }
|
||||
if (draft != null) {
|
||||
|
||||
+9
-1
@@ -67,6 +67,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.alias.matches
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard
|
||||
import io.element.android.libraries.ui.utils.a11y.isTalkbackActive
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
@@ -112,7 +113,7 @@ class ThreadedMessagesNode(
|
||||
this.timelineController = timelineController
|
||||
return presenterFactory.create(
|
||||
navigator = this,
|
||||
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true),
|
||||
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = inputs.threadRootEventId),
|
||||
timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this),
|
||||
// TODO add special processor for threaded timeline
|
||||
actionListPresenter = actionListPresenterFactory.create(
|
||||
@@ -138,6 +139,8 @@ class ThreadedMessagesNode(
|
||||
fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean)
|
||||
fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?)
|
||||
fun navigateToDeveloperSettings()
|
||||
|
||||
fun navigateToAvatarPreview(username: String, avatarUrl: String)
|
||||
}
|
||||
|
||||
override fun onBuilt() {
|
||||
@@ -315,6 +318,11 @@ class ThreadedMessagesNode(
|
||||
else -> state.roomMemberModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target))
|
||||
}
|
||||
},
|
||||
onAvatarClick = { user ->
|
||||
user.avatarUrl?.let { url ->
|
||||
callback.navigateToAvatarPreview(user.getBestName(), url)
|
||||
}
|
||||
},
|
||||
modifier = Modifier,
|
||||
)
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
<string name="emoji_picker_category_symbols">"Сімвалы"</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз."</string>
|
||||
<string name="screen_media_upload_preview_processing">"Апрацоўка…"</string>
|
||||
<string name="screen_media_upload_preview_title">"Дадаць медыя"</string>
|
||||
<string name="screen_report_content_block_user">"Заблакіраваць карыстальніка"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Адзначце, ці хочаце вы схаваць усе бягучыя і будучыя паведамленні ад гэтага карыстальніка"</string>
|
||||
<string name="screen_report_content_explanation">"Гэтае паведамленне будзе перададзена адміністратару вашага хатняга сервера. Яны не змогуць прачытаць зашыфраваныя паведамленні."</string>
|
||||
@@ -25,7 +27,7 @@
|
||||
<string name="screen_room_attachment_source_camera_video">"Запісаць відэа"</string>
|
||||
<string name="screen_room_attachment_source_files">"Далучэнне"</string>
|
||||
<string name="screen_room_attachment_source_gallery">"Бібліятэка фота & відэа"</string>
|
||||
<string name="screen_room_attachment_source_location">"Месцазнаходжанне"</string>
|
||||
<string name="screen_room_attachment_source_location">"Абагуліць месцазнаходжанне"</string>
|
||||
<string name="screen_room_attachment_source_poll">"Апытанне"</string>
|
||||
<string name="screen_room_attachment_text_formatting">"Фармаціраванне тэксту"</string>
|
||||
<string name="screen_room_encrypted_history_banner">"Гісторыя паведамленняў зараз недаступна."</string>
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<string name="emoji_picker_category_places">"Путешествия и места"</string>
|
||||
<string name="emoji_picker_category_recent">"Недавние эмодзи"</string>
|
||||
<string name="emoji_picker_category_symbols">"Символы"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally">"Перевернуть изображение по горизонтали"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally_state_flipped">"Перевернуто по горизонтали"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally_state_original">"Оригинал"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically">"Перевернуть изображение по вертикали"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically_state_flipped">"Перевернуто по вертикали"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically_state_original">"Оригинал"</string>
|
||||
<string name="screen_image_edition_a11y_rotate_to_the_left">"Повернуть изображение влево."</string>
|
||||
<plurals name="screen_image_edition_a11y_rotation_state">
|
||||
<item quantity="one">"%1$d градус"</item>
|
||||
@@ -26,8 +32,8 @@
|
||||
<string name="screen_media_upload_preview_caption_warning">"Подпись может быть не видна пользователям старых приложений."</string>
|
||||
<string name="screen_media_upload_preview_change_video_quality_prompt">"Нажмите, чтобы изменить качество загружаемого видео."</string>
|
||||
<string name="screen_media_upload_preview_error_could_not_be_uploaded">"Файл не может быть загружен."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Не удалось обработать медиафайл для загрузки, попробуйте еще раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Не удалось загрузить медиафайлы, попробуйте еще раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Не удалось обработать медиафайл для загрузки, попробуйте ещё раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Не удалось загрузить медиафайлы, попробуйте ещё раз."</string>
|
||||
<string name="screen_media_upload_preview_error_too_large_message">"Максимальный размер файла: %1$s."</string>
|
||||
<string name="screen_media_upload_preview_error_too_large_title">"Файл слишком большой для загрузки."</string>
|
||||
<string name="screen_media_upload_preview_item_count">"%1$d из %2$d"</string>
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
<string name="emoji_picker_category_places">"Подорожі та місця"</string>
|
||||
<string name="emoji_picker_category_recent">"Нещодавні емодзі"</string>
|
||||
<string name="emoji_picker_category_symbols">"Символи"</string>
|
||||
<string name="screen_image_edition_a11y_rotate_to_the_left">"Повернути зображення вліво"</string>
|
||||
<plurals name="screen_image_edition_a11y_rotation_state">
|
||||
<item quantity="one">"%1$d градус"</item>
|
||||
<item quantity="few">"%1$d градуси"</item>
|
||||
<item quantity="many">"%1$d градусів"</item>
|
||||
</plurals>
|
||||
<string name="screen_image_edition_title">"Редагувати фото"</string>
|
||||
<string name="screen_media_upload_preview_caption_warning">"Користувачі старих застосунків можуть не бачити підписи."</string>
|
||||
<string name="screen_media_upload_preview_change_video_quality_prompt">"Натисніть, щоб змінити якість вивантажуваного відео"</string>
|
||||
<string name="screen_media_upload_preview_error_could_not_be_uploaded">"Файл не може бути вивантажено."</string>
|
||||
@@ -26,6 +33,7 @@
|
||||
<string name="screen_media_upload_preview_item_count">"Елемент %1$d з %2$d"</string>
|
||||
<string name="screen_media_upload_preview_optimize_image_quality_title">"Оптимізувати якість зображення"</string>
|
||||
<string name="screen_media_upload_preview_processing">"Обробка…"</string>
|
||||
<string name="screen_media_upload_preview_title">"Додати медіа"</string>
|
||||
<string name="screen_report_content_block_user">"Заблокувати користувача"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Перевірте, чи хочете ви приховати всі поточні та майбутні повідомлення від цього користувача"</string>
|
||||
<string name="screen_report_content_explanation">"Це повідомлення буде надіслано адміністраторам вашого домашнього сервера. Вони не зможуть прочитати зашифровані повідомлення."</string>
|
||||
|
||||
+3
-2
@@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter
|
||||
import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper
|
||||
import io.element.android.features.messages.impl.utils.TextPillificationHelper
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
||||
@@ -271,12 +272,12 @@ class MessageComposerPresenterSlashCommandTest {
|
||||
isRichTextEditorEnabled: Boolean = true,
|
||||
draftService: ComposerDraftService = FakeComposerDraftService(),
|
||||
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
|
||||
isInThread: Boolean = false,
|
||||
threadRoot: ThreadId? = null,
|
||||
slashCommandService: SlashCommandService = FakeSlashCommandService(),
|
||||
) = MessageComposerPresenter(
|
||||
navigator = navigator,
|
||||
sessionCoroutineScope = this,
|
||||
isInThread = isInThread,
|
||||
threadRoot = threadRoot,
|
||||
room = room,
|
||||
mediaPickerProvider = pickerProvider,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
|
||||
+2
-2
@@ -1534,12 +1534,12 @@ class MessageComposerPresenterTest {
|
||||
isRichTextEditorEnabled: Boolean = true,
|
||||
draftService: ComposerDraftService = FakeComposerDraftService(),
|
||||
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
|
||||
isInThread: Boolean = false,
|
||||
threadRoot: ThreadId? = null,
|
||||
slashCommandService: SlashCommandService = FakeSlashCommandService(),
|
||||
) = MessageComposerPresenter(
|
||||
navigator = navigator,
|
||||
sessionCoroutineScope = this,
|
||||
isInThread = isInThread,
|
||||
threadRoot = threadRoot,
|
||||
room = room,
|
||||
mediaPickerProvider = pickerProvider,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
<string name="screen_advanced_settings_media_compression_description">"Загружайте фотографии и видео быстрее и сокращайте потребление трафика"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Оптимизировать качество мультимедиа"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Модерация и безопасность"</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_description">"Автоматически оптимизируйте изображения для более быстрой загрузки и уменьшения размера файлов."</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_title">"Оптимизируйте качество загрузки изображения"</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_description">"Автоматически оптимизировать изображения для более быстрой загрузки и уменьшения размера файлов."</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_title">"Оптимизировать качество загрузки изображений"</string>
|
||||
<string name="screen_advanced_settings_optimise_video_upload_quality_description">"%1$s. Нажмите здесь, чтобы изменить."</string>
|
||||
<string name="screen_advanced_settings_optimise_video_upload_quality_high">"Высокое (1080p)"</string>
|
||||
<string name="screen_advanced_settings_optimise_video_upload_quality_low">"Низкое (480p)"</string>
|
||||
@@ -35,14 +35,14 @@
|
||||
<string name="screen_advanced_settings_send_read_receipts">"Уведомления о прочтении"</string>
|
||||
<string name="screen_advanced_settings_send_read_receipts_description">"Если этот параметр выключен, другие пользователи не будут видеть, прочитали ли вы сообщения. Вы по-прежнему будете видеть статус прочтения других пользователей."</string>
|
||||
<string name="screen_advanced_settings_share_presence">"Делиться присутствием"</string>
|
||||
<string name="screen_advanced_settings_share_presence_description">"Если выключено, вы не будете видеть, кто печатает и читает сообщения, а также другие пользователи не будут знать, когда вы печатаете или читаете сообщения."</string>
|
||||
<string name="screen_advanced_settings_share_presence_description">"Если выключено, Вы не будете видеть, кто печатает и читает сообщения, а также другие пользователи не будут знать, когда Вы печатаете или читаете сообщения."</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_always_hide">"Всегда скрывать"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_always_show">"Всегда показывать"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_private_rooms">"В приватных комнатах"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_subtitle">"Скрытые медиа всегда можно просмотреть, нажав на них."</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_title">"Показать медиа в истории сообщений"</string>
|
||||
<string name="screen_advanced_settings_view_source_description">"Включить опцию просмотра источника сообщения в истории сообщений."</string>
|
||||
<string name="screen_blocked_users_empty">"У вас нет заблокированных пользователей"</string>
|
||||
<string name="screen_blocked_users_empty">"У Вас нет заблокированных пользователей"</string>
|
||||
<string name="screen_blocked_users_unblock_alert_action">"Разблокировать"</string>
|
||||
<string name="screen_blocked_users_unblock_alert_description">"Вы снова сможете увидеть все сообщения."</string>
|
||||
<string name="screen_blocked_users_unblock_alert_title">"Разблокировать пользователя"</string>
|
||||
@@ -59,11 +59,12 @@
|
||||
<string name="screen_labs_header_title">"Хотите попробовать?"</string>
|
||||
<string name="screen_labs_title">"Лаборатория"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Дополнительные параметры"</string>
|
||||
<string name="screen_notification_settings_call_ringtone_label">"Мелодия звонка"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Аудио и видео звонки"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Несоответствие конфигурации"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch_description">"Мы упростили настройки уведомлений, чтобы упростить поиск опций. Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они все еще активны.
|
||||
<string name="screen_notification_settings_configuration_mismatch_description">"Мы упростили настройки уведомлений, чтобы упростить поиск опций. Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они всё ещё активны.
|
||||
|
||||
Если вы продолжите, некоторые настройки могут быть изменены."</string>
|
||||
Если Вы продолжите, некоторые настройки могут быть изменены."</string>
|
||||
<string name="screen_notification_settings_direct_chats">"В личных чатах"</string>
|
||||
<string name="screen_notification_settings_edit_custom_settings_section_title">"Отдельные настройки для каждого чата"</string>
|
||||
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Произошла ошибка при обновлении настройки уведомления."</string>
|
||||
@@ -72,22 +73,30 @@
|
||||
<string name="screen_notification_settings_edit_screen_direct_section_header">"Уведомлять меня в личных чатах"</string>
|
||||
<string name="screen_notification_settings_edit_screen_group_section_header">"Уведомлять меня в групповых чатах"</string>
|
||||
<string name="screen_notification_settings_enable_notifications">"Включить уведомления на данном устройстве"</string>
|
||||
<string name="screen_notification_settings_failed_fixing_configuration">"Конфигурация не была исправлена, попробуйте еще раз."</string>
|
||||
<string name="screen_notification_settings_failed_fixing_configuration">"Конфигурация не была исправлена, попробуйте ещё раз."</string>
|
||||
<string name="screen_notification_settings_group_chats">"В групповых чатах"</string>
|
||||
<string name="screen_notification_settings_invite_for_me_label">"Приглашения"</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш сервер не поддерживает эту опцию для зашифрованных комнат, вы можете не получать некоторые уведомления."</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш сервер не поддерживает эту опцию для зашифрованных комнат, Вы можете не получать некоторые уведомления."</string>
|
||||
<string name="screen_notification_settings_mentions_section_title">"Упоминания"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_choose_other">"Выбрать другой звук…"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_current_subtitle">"Сейчас используется %1$s"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_title">"Звук сообщения"</string>
|
||||
<string name="screen_notification_settings_message_sound_label">"Звук сообщения"</string>
|
||||
<string name="screen_notification_settings_mode_all">"Все"</string>
|
||||
<string name="screen_notification_settings_mode_mentions">"Упоминания"</string>
|
||||
<string name="screen_notification_settings_notification_section_title">"Уведомлять меня"</string>
|
||||
<string name="screen_notification_settings_room_mention_label">"Уведомлять меня при упоминании @room"</string>
|
||||
<string name="screen_notification_settings_sound_custom_fallback">"Пользовательский"</string>
|
||||
<string name="screen_notification_settings_sound_custom_sound_button_title">"Пользовательский звук…"</string>
|
||||
<string name="screen_notification_settings_sound_delete_sound_error_title">"Ошибка при удалении файла"</string>
|
||||
<string name="screen_notification_settings_sound_element_default">"Element по умолчанию"</string>
|
||||
<string name="screen_notification_settings_sound_element_fade">"Element Fade"</string>
|
||||
<string name="screen_notification_settings_sound_import_sound_error_title">"Ошибка импорта файла"</string>
|
||||
<string name="screen_notification_settings_sound_preview_sound_error_title">"Ошибка предварительного прослушиванием звука"</string>
|
||||
<string name="screen_notification_settings_sound_section_title">"Звук"</string>
|
||||
<string name="screen_notification_settings_sound_set_sound_error_dismiss_a11y">"Отклонить ошибку о звуке"</string>
|
||||
<string name="screen_notification_settings_sound_set_sound_error_title">"Проблема с настройкой звукового оповещения"</string>
|
||||
<string name="screen_notification_settings_sound_silent">"Без звука"</string>
|
||||
<string name="screen_notification_settings_sound_system_alert">"Оповещение"</string>
|
||||
<string name="screen_notification_settings_sound_system_anticipate">"Anticipate"</string>
|
||||
<string name="screen_notification_settings_sound_system_bell">"Bell"</string>
|
||||
@@ -95,6 +104,7 @@
|
||||
<string name="screen_notification_settings_sound_system_calypso">"Calypso"</string>
|
||||
<string name="screen_notification_settings_sound_system_chime">"Chime"</string>
|
||||
<string name="screen_notification_settings_sound_system_choo_choo">"Choo Choo"</string>
|
||||
<string name="screen_notification_settings_sound_system_default">"Как в системе"</string>
|
||||
<string name="screen_notification_settings_sound_system_descent">"Descent"</string>
|
||||
<string name="screen_notification_settings_sound_system_electronic">"Electronic"</string>
|
||||
<string name="screen_notification_settings_sound_system_fanfare">"Fanfare"</string>
|
||||
@@ -124,5 +134,5 @@
|
||||
<string name="theme_system">"Системное"</string>
|
||||
<string name="troubleshoot_notifications_entry_point_push_history_title">"История уведомлений"</string>
|
||||
<string name="troubleshoot_notifications_entry_point_section">"Устранение неполадок"</string>
|
||||
<string name="troubleshoot_notifications_entry_point_title">"Уведомления об устранении неполадок"</string>
|
||||
<string name="troubleshoot_notifications_entry_point_title">"Устранение неполадок с уведомлениями"</string>
|
||||
</resources>
|
||||
|
||||
@@ -81,10 +81,45 @@
|
||||
<string name="screen_notification_settings_mode_mentions">"Згадки"</string>
|
||||
<string name="screen_notification_settings_notification_section_title">"Сповіщати мене про"</string>
|
||||
<string name="screen_notification_settings_room_mention_label">"Сповіщати про @room"</string>
|
||||
<string name="screen_notification_settings_sound_custom_sound_button_title">"Користувацький звук…"</string>
|
||||
<string name="screen_notification_settings_sound_delete_sound_error_title">"Помилка видалення файлу"</string>
|
||||
<string name="screen_notification_settings_sound_element_default">"За замовчуванням Element"</string>
|
||||
<string name="screen_notification_settings_sound_element_fade">"Згасання Element"</string>
|
||||
<string name="screen_notification_settings_sound_import_sound_error_title">"Помилка імпорту файлу"</string>
|
||||
<string name="screen_notification_settings_sound_preview_sound_error_title">"Проблема з попереднім прослуховуванням звуку сповіщення"</string>
|
||||
<string name="screen_notification_settings_sound_section_title">"Звук"</string>
|
||||
<string name="screen_notification_settings_sound_set_sound_error_title">"Проблема налаштовування звуку сповіщення"</string>
|
||||
<string name="screen_notification_settings_sound_system_alert">"Тривога"</string>
|
||||
<string name="screen_notification_settings_sound_system_anticipate">"Передбачення"</string>
|
||||
<string name="screen_notification_settings_sound_system_bell">"Дзвоник"</string>
|
||||
<string name="screen_notification_settings_sound_system_bloom">"Цвітіння"</string>
|
||||
<string name="screen_notification_settings_sound_system_calypso">"Каліпсо"</string>
|
||||
<string name="screen_notification_settings_sound_system_chime">"Передзвін"</string>
|
||||
<string name="screen_notification_settings_sound_system_choo_choo">"Чу-чу"</string>
|
||||
<string name="screen_notification_settings_sound_system_descent">"Спуск"</string>
|
||||
<string name="screen_notification_settings_sound_system_electronic">"Електроніка"</string>
|
||||
<string name="screen_notification_settings_sound_system_fanfare">"Фанфари"</string>
|
||||
<string name="screen_notification_settings_sound_system_glass">"Скло"</string>
|
||||
<string name="screen_notification_settings_sound_system_horn">"Ріг"</string>
|
||||
<string name="screen_notification_settings_sound_system_ladder">"Драбина"</string>
|
||||
<string name="screen_notification_settings_sound_system_minuet">"Менует"</string>
|
||||
<string name="screen_notification_settings_sound_system_news_flash">"Екстренні новини"</string>
|
||||
<string name="screen_notification_settings_sound_system_noir">"Нуар"</string>
|
||||
<string name="screen_notification_settings_sound_system_sherwood_forest">"Шервудський ліс"</string>
|
||||
<string name="screen_notification_settings_sound_system_spell">"Чаклування"</string>
|
||||
<string name="screen_notification_settings_sound_system_suspense">"Інтрига"</string>
|
||||
<string name="screen_notification_settings_sound_system_swish">"Свист"</string>
|
||||
<string name="screen_notification_settings_sound_system_telegraph">"Телеграф"</string>
|
||||
<string name="screen_notification_settings_sound_system_tiptoes">"Навшпиньки"</string>
|
||||
<string name="screen_notification_settings_sound_system_tri_tone">"Тритональний"</string>
|
||||
<string name="screen_notification_settings_sound_system_tweet">"Твіт"</string>
|
||||
<string name="screen_notification_settings_sound_system_typewriters">"Друкарські машинки"</string>
|
||||
<string name="screen_notification_settings_sound_system_update">"Оновити"</string>
|
||||
<string name="screen_notification_settings_system_notifications_action_required">"Щоб отримувати сповіщення змініть свої %1$s."</string>
|
||||
<string name="screen_notification_settings_system_notifications_action_required_content_link">"системні налаштування"</string>
|
||||
<string name="screen_notification_settings_system_notifications_turned_off">"Системні сповіщення вимкнені"</string>
|
||||
<string name="screen_notification_settings_title">"Сповіщення"</string>
|
||||
<string name="theme_black">"Темна"</string>
|
||||
<string name="theme_dark">"Темна"</string>
|
||||
<string name="theme_light">"Світла"</string>
|
||||
<string name="theme_system">"Системна"</string>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crash_detection_dialog_content">"Пры апошнім выкарыстанні %1$s адбыўся збой. Хочаце падзяліцца справаздачай аб збоі?"</string>
|
||||
<string name="crash_detection_dialog_content">"Пры апошнім выкарыстанні %1$s адбыўся збой. Хочаце абагуліць справаздачу аб збоі?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Падобна, што вы трасеце тэлефон. Хочаце адкрыць экран паведамлення пра памылку?"</string>
|
||||
<string name="settings_rageshake">"Rageshake"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Парог выяўлення"</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crash_detection_dialog_content">"При последнем использовании %1$s произошел сбой. Хотите отправить отчет?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Похоже, что вы трясете телефон. Хотите открыть экран сообщения об ошибке?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Похоже, что Вы трясете телефон в раздражении. Хотите открыть экран сообщения об ошибке?"</string>
|
||||
<string name="settings_rageshake">"Встряхните"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Порог обнаружения"</string>
|
||||
</resources>
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
<string name="screen_bug_report_include_logs">"Дазволіць журналы"</string>
|
||||
<string name="screen_bug_report_include_screenshot">"Адправіць здымак экрана"</string>
|
||||
<string name="screen_bug_report_logs_description">"Каб пераканацца, што ўсё працуе правільна, у паведамленне будуць уключаны часопісы. Каб адправіць паведамленне без часопісаў, адключыце гэтую наладу."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"Пры апошнім выкарыстанні %1$s адбыўся збой. Хочаце падзяліцца справаздачай аб збоі?"</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"Пры апошнім выкарыстанні %1$s адбыўся збой. Хочаце абагуліць справаздачу аб збоі?"</string>
|
||||
<string name="screen_bug_report_view_logs">"Прагляд журналаў"</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
<string name="screen_bug_report_editor_placeholder">"Опишите проблему…"</string>
|
||||
<string name="screen_bug_report_editor_supporting">"Если возможно, пожалуйста, напишите описание на английском языке."</string>
|
||||
<string name="screen_bug_report_error_description_too_short">"Описание слишком короткое, пожалуйста, расскажите подробнее о том, что произошло. Спасибо!"</string>
|
||||
<string name="screen_bug_report_github_issue_description">"При наличии, Вы можете ввести номер связанной проблемы из GitHub."</string>
|
||||
<string name="screen_bug_report_github_issue_label">"Проблема на GitHub"</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"Отправка журналов сбоев"</string>
|
||||
<string name="screen_bug_report_include_logs">"Разрешить ведение журналов"</string>
|
||||
<string name="screen_bug_report_include_logs_error">"Ваши журналы слишком большие для включения в этот отчет. Пожалуйста, отправьте их нам другим способом."</string>
|
||||
<string name="screen_bug_report_include_screenshot">"Отправить скриншот"</string>
|
||||
<string name="screen_bug_report_logs_description">"Чтобы убедиться, что всё работает правильно, к сообщению будут прикреплены журналы. Чтобы отправить сообщение без журналов, отключите эту настройку."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"При последнем использовании %1$s произошел сбой. Хотите отправить отчет?"</string>
|
||||
<string name="screen_bug_report_send_notification_settings_description">"Если у вас возникли проблемы с уведомлениями, загрузка настроек уведомлений может помочь нам определить основную причину."</string>
|
||||
<string name="screen_bug_report_send_notification_settings_description">"Если у Вас возникли проблемы с уведомлениями, загрузка настроек уведомлений может помочь нам определить причину проблемы. Обратите внимание, что эти правила могут содержать конфиденциальную информацию, такую как Ваше отображаемое имя или ключевые слова, по которым должны срабатывать уведомления."</string>
|
||||
<string name="screen_bug_report_send_notification_settings_title">"Настройки отправки уведомлений"</string>
|
||||
<string name="screen_bug_report_view_logs">"Просмотр журналов"</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<string name="screen_bug_report_editor_placeholder">"Опишіть проблему…"</string>
|
||||
<string name="screen_bug_report_editor_supporting">"Якщо можливо, будь ласка, напишіть опис англійською мовою."</string>
|
||||
<string name="screen_bug_report_error_description_too_short">"Опис закороткий, будь ласка, надайте докладнішу інформацію про те, що сталося. Дякуємо!"</string>
|
||||
<string name="screen_bug_report_github_issue_description">"Ви можете ввести номер вже існуючої проблеми на GitHub, якщо така є."</string>
|
||||
<string name="screen_bug_report_github_issue_label">"Тікет на GitHub"</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"Надіслати журнали збоїв"</string>
|
||||
<string name="screen_bug_report_include_logs">"Дозволити журнали"</string>
|
||||
<string name="screen_bug_report_include_logs_error">"Ваші журнали надмірно великі, тому їх не можна включити в цей звіт, будь ласка, надішліть їх нам іншим способом."</string>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_report_room_leave_failed_alert_message">"Ваша жалоба была успешно отправлена, но мы столкнулись с проблемой при попытке покинуть комнату. Пожалуйста, попробуйте еще раз."</string>
|
||||
<string name="screen_report_room_leave_failed_alert_message">"Ваша жалоба была успешно отправлена, но мы столкнулись с проблемой при попытке покинуть комнату. Пожалуйста, попробуйте ещё раз."</string>
|
||||
<string name="screen_report_room_leave_failed_alert_title">"Невозможно покинуть комнату"</string>
|
||||
<string name="screen_report_room_reason_footer">"Пожалуйтесь на комнату администратору. Если сообщения зашифрованы, ваш администратор не сможет их прочитать."</string>
|
||||
<string name="screen_report_room_reason_placeholder">"Опишите причину жалобы…"</string>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_change_permissions_administrators">"Толькі адміністратары"</string>
|
||||
<string name="screen_room_change_permissions_administrators">"Адміністратар"</string>
|
||||
<string name="screen_room_change_permissions_ban_people">"Заблакіраваць людзей"</string>
|
||||
<string name="screen_room_change_permissions_delete_messages">"Выдаліць паведамленні"</string>
|
||||
<string name="screen_room_change_permissions_invite_people">"Запрашайце людзей і прымайце запыты на далучэнне"</string>
|
||||
<string name="screen_room_change_permissions_everyone">"Удзельнік"</string>
|
||||
<string name="screen_room_change_permissions_invite_people">"Запрасіць людзей"</string>
|
||||
<string name="screen_room_change_permissions_messages_and_content">"Паведамленні і змест"</string>
|
||||
<string name="screen_room_change_permissions_moderators">"Адміністратары і мадэратары"</string>
|
||||
<string name="screen_room_change_permissions_moderators">"Мадэратар"</string>
|
||||
<string name="screen_room_change_permissions_remove_people">"Выдаляйце людзей і адхіляйце запыты на далучэнне"</string>
|
||||
<string name="screen_room_change_permissions_room_avatar">"Змяніць аватар пакоя"</string>
|
||||
<string name="screen_room_change_permissions_room_details">"Рэдагаваць пакой"</string>
|
||||
@@ -39,8 +40,8 @@
|
||||
<string name="screen_room_member_list_manage_member_unban_message">"Яны змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць."</string>
|
||||
<string name="screen_room_member_list_mode_banned">"Заблакіраваныя"</string>
|
||||
<string name="screen_room_member_list_mode_members">"Удзельнікі"</string>
|
||||
<string name="screen_room_member_list_role_administrator">"Толькі адміністратары"</string>
|
||||
<string name="screen_room_member_list_role_moderator">"Адміністратары і мадэратары"</string>
|
||||
<string name="screen_room_member_list_role_administrator">"Адміністратар"</string>
|
||||
<string name="screen_room_member_list_role_moderator">"Мадэратар"</string>
|
||||
<string name="screen_room_member_list_room_members_header_title">"Удзельнікі пакоя"</string>
|
||||
<string name="screen_room_member_list_unbanning_user">"Разблакіроўка %1$s"</string>
|
||||
<string name="screen_room_roles_and_permissions_admins">"Адміністратары"</string>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<string name="screen_room_change_permissions_send_messages">"Отправлять сообщения"</string>
|
||||
<string name="screen_room_change_permissions_title">"Разрешения"</string>
|
||||
<string name="screen_room_change_role_administrators_title">"Редактировать администраторов"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не сможете отменить это действие. Вы даете пользователю такой же уровень прав, как и у вас"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не сможете отменить это действие. Вы даете пользователю такой же уровень прав, как и у Вас"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_title">"Добавить администратора?"</string>
|
||||
<string name="screen_room_change_role_confirm_change_owners_description">"Отменить данное действие будет невозможно. Права передадутся выбранным пользователям. После вашего выхода действие станет необратимым."</string>
|
||||
<string name="screen_room_change_role_confirm_change_owners_title">"Передать владение?"</string>
|
||||
@@ -36,7 +36,7 @@
|
||||
<string name="screen_room_change_role_section_administrators">"Администраторы"</string>
|
||||
<string name="screen_room_change_role_section_moderators">"Модераторы"</string>
|
||||
<string name="screen_room_change_role_section_users">"Участники"</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_description">"У вас есть несохраненные изменения."</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_description">"У Вас есть несохраненные изменения."</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_title">"Сохранить изменения?"</string>
|
||||
<string name="screen_room_member_list_banned_empty">"В этой комнате нет заблокированных пользователей."</string>
|
||||
<plurals name="screen_room_member_list_banned_header_title">
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<string name="screen_room_change_permissions_delete_messages">"Вилучати повідомлення"</string>
|
||||
<string name="screen_room_change_permissions_everyone">"Учасник"</string>
|
||||
<string name="screen_room_change_permissions_invite_people">"Запрошувати людей"</string>
|
||||
<string name="screen_room_change_permissions_live_location">"Ділитися місцезнаходженням у реальному часі"</string>
|
||||
<string name="screen_room_change_permissions_manage_space">"Керувати простором"</string>
|
||||
<string name="screen_room_change_permissions_manage_space_rooms">"Керувати кімнатами"</string>
|
||||
<string name="screen_room_change_permissions_member_moderation">"Керувати учасниками"</string>
|
||||
|
||||
+4
@@ -258,6 +258,10 @@ class RoomDetailsFlowNode(
|
||||
override fun navigateToInviteMembers() {
|
||||
backstack.push(NavTarget.InviteMembers)
|
||||
}
|
||||
|
||||
override fun navigateToAvatarPreview(username: String, avatarUrl: String) {
|
||||
overlay.show(NavTarget.AvatarPreview(username, avatarUrl))
|
||||
}
|
||||
}
|
||||
createNode<RoomMemberListNode>(buildContext, listOf(roomMemberListCallback))
|
||||
}
|
||||
|
||||
+7
@@ -27,6 +27,7 @@ import io.element.android.libraries.architecture.appyx.launchMolecule
|
||||
import io.element.android.libraries.architecture.callback
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
|
||||
@ContributesNode(RoomScope::class)
|
||||
@@ -41,6 +42,7 @@ class RoomMemberListNode(
|
||||
interface Callback : Plugin {
|
||||
fun navigateToRoomMemberDetails(roomMemberId: UserId)
|
||||
fun navigateToInviteMembers()
|
||||
fun navigateToAvatarPreview(username: String, avatarUrl: String)
|
||||
}
|
||||
|
||||
private val callback: Callback = callback()
|
||||
@@ -82,6 +84,11 @@ class RoomMemberListNode(
|
||||
else -> state.moderationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target))
|
||||
}
|
||||
},
|
||||
onAvatarClick = { user ->
|
||||
user.avatarUrl?.let { url ->
|
||||
callback.navigateToAvatarPreview(user.getBestName(), url)
|
||||
}
|
||||
},
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_edit_room_address_title">"Рэдагаваць адрас"</string>
|
||||
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Пры абнаўленні налад апавяшчэнняў адбылася памылка."</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш хатні сервер не падтрымлівае гэтую опцыю ў зашыфраваных пакоях, вы можаце не атрымаць апавяшчэнне ў некаторых пакоях."</string>
|
||||
<string name="screen_polls_history_title">"Апытанні"</string>
|
||||
<string name="screen_room_change_permissions_administrators">"Толькі адміністратары"</string>
|
||||
<string name="screen_room_change_permissions_administrators">"Адміністратар"</string>
|
||||
<string name="screen_room_change_permissions_ban_people">"Заблакіраваць людзей"</string>
|
||||
<string name="screen_room_change_permissions_delete_messages">"Выдаліць паведамленні"</string>
|
||||
<string name="screen_room_change_permissions_invite_people">"Запрашайце людзей і прымайце запыты на далучэнне"</string>
|
||||
<string name="screen_room_change_permissions_everyone">"Удзельнік"</string>
|
||||
<string name="screen_room_change_permissions_invite_people">"Запрасіць людзей"</string>
|
||||
<string name="screen_room_change_permissions_messages_and_content">"Паведамленні і змест"</string>
|
||||
<string name="screen_room_change_permissions_moderators">"Адміністратары і мадэратары"</string>
|
||||
<string name="screen_room_change_permissions_moderators">"Мадэратар"</string>
|
||||
<string name="screen_room_change_permissions_remove_people">"Выдаляйце людзей і адхіляйце запыты на далучэнне"</string>
|
||||
<string name="screen_room_change_permissions_room_avatar">"Змяніць аватар пакоя"</string>
|
||||
<string name="screen_room_change_permissions_room_details">"Рэдагаваць пакой"</string>
|
||||
@@ -52,8 +54,9 @@
|
||||
<string name="screen_room_details_pinned_events_row_title">"Замацаваныя паведамленні"</string>
|
||||
<string name="screen_room_details_profile_row_title">"Профіль"</string>
|
||||
<string name="screen_room_details_roles_and_permissions">"Ролі і дазволы"</string>
|
||||
<string name="screen_room_details_room_name_label">"Імя"</string>
|
||||
<string name="screen_room_details_security_title">"Бяспека"</string>
|
||||
<string name="screen_room_details_share_room_title">"Падзяліцца пакоем"</string>
|
||||
<string name="screen_room_details_share_room_title">"Абагуліць пакой"</string>
|
||||
<string name="screen_room_details_title">"Інфармацыя аб пакоі"</string>
|
||||
<string name="screen_room_details_topic_title">"Тэма"</string>
|
||||
<string name="screen_room_details_updating_room">"Ідзе абнаўленне пакоя…"</string>
|
||||
@@ -69,8 +72,8 @@
|
||||
<string name="screen_room_member_list_manage_member_unban_message">"Яны змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць."</string>
|
||||
<string name="screen_room_member_list_mode_banned">"Заблакіраваныя"</string>
|
||||
<string name="screen_room_member_list_mode_members">"Удзельнікі"</string>
|
||||
<string name="screen_room_member_list_role_administrator">"Толькі адміністратары"</string>
|
||||
<string name="screen_room_member_list_role_moderator">"Адміністратары і мадэратары"</string>
|
||||
<string name="screen_room_member_list_role_administrator">"Адміністратар"</string>
|
||||
<string name="screen_room_member_list_role_moderator">"Мадэратар"</string>
|
||||
<string name="screen_room_member_list_room_members_header_title">"Удзельнікі пакоя"</string>
|
||||
<string name="screen_room_member_list_unbanning_user">"Разблакіроўка %1$s"</string>
|
||||
<string name="screen_room_notification_settings_allow_custom">"Дазволіць уласную наладу"</string>
|
||||
@@ -102,4 +105,5 @@
|
||||
<string name="screen_room_roles_and_permissions_title">"Ролі і дазволы"</string>
|
||||
<string name="screen_roomlist_mark_as_read">"Пазначыць як прачытанае"</string>
|
||||
<string name="screen_roomlist_mark_as_unread">"Пазначыць як непрачытанае"</string>
|
||||
<string name="screen_security_and_privacy_room_address_section_header">"Адрас"</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="screen_edit_room_address_room_address_section_footer">"Необходимо задать адрес комнаты, чтобы опубликовать ее в каталоге комнат."</string>
|
||||
<string name="screen_edit_room_address_title">"Редактировать адрес комнаты"</string>
|
||||
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Произошла ошибка при обновлении настройки уведомления."</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш сервер не поддерживает эту опцию для зашифрованных комнат, вы можете не получать некоторые уведомления."</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш сервер не поддерживает эту опцию для зашифрованных комнат, Вы можете не получать некоторые уведомления."</string>
|
||||
<string name="screen_polls_history_title">"Опросы"</string>
|
||||
<string name="screen_room_change_permissions_administrators">"Администраторы"</string>
|
||||
<string name="screen_room_change_permissions_ban_people">"Блокировать пользователей"</string>
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="screen_room_change_permissions_room_topic">"Менять тему комнаты"</string>
|
||||
<string name="screen_room_change_permissions_send_messages">"Отправлять сообщения"</string>
|
||||
<string name="screen_room_change_role_administrators_title">"Редактировать администраторов"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не сможете отменить это действие. Вы даете пользователю такой же уровень прав, как и у вас"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не сможете отменить это действие. Вы даете пользователю такой же уровень прав, как и у Вас"</string>
|
||||
<string name="screen_room_change_role_confirm_add_admin_title">"Добавить администратора?"</string>
|
||||
<string name="screen_room_change_role_confirm_change_owners_description">"Отменить данное действие будет невозможно. Права передадутся выбранным пользователям. После вашего выхода действие станет необратимым."</string>
|
||||
<string name="screen_room_change_role_confirm_change_owners_title">"Передать владение?"</string>
|
||||
@@ -39,7 +39,7 @@
|
||||
<string name="screen_room_change_role_section_administrators">"Администраторы"</string>
|
||||
<string name="screen_room_change_role_section_moderators">"Модераторы"</string>
|
||||
<string name="screen_room_change_role_section_users">"Участники"</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_description">"У вас есть несохраненные изменения."</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_description">"У Вас есть несохраненные изменения."</string>
|
||||
<string name="screen_room_change_role_unsaved_changes_title">"Сохранить изменения?"</string>
|
||||
<string name="screen_room_details_add_topic_title">"Добавить тему"</string>
|
||||
<string name="screen_room_details_badge_encrypted">"Зашифровано"</string>
|
||||
@@ -51,8 +51,8 @@
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Сообщения зашифрованы. Только вы и ваши собеседники имеют доступ к сообщениям."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Шифрование сообщений включено"</string>
|
||||
<string name="screen_room_details_error_loading_notification_settings">"Произошла ошибка при загрузке настроек уведомлений."</string>
|
||||
<string name="screen_room_details_error_muting">"Не удалось отключить звук в этой комнате, попробуйте еще раз."</string>
|
||||
<string name="screen_room_details_error_unmuting">"Не удалось включить звук в эту комнату, попробуйте еще раз."</string>
|
||||
<string name="screen_room_details_error_muting">"Не удалось отключить звук в этой комнате, попробуйте ещё раз."</string>
|
||||
<string name="screen_room_details_error_unmuting">"Не удалось включить звук в этой комнате, попробуйте ещё раз."</string>
|
||||
<string name="screen_room_details_invite_people_dont_close">"Не закрывайте приложение, пока не закончите."</string>
|
||||
<string name="screen_room_details_invite_people_preparing">"Подготовка приглашений…"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Пригласить в комнату"</string>
|
||||
@@ -63,7 +63,7 @@
|
||||
<string name="screen_room_details_notification_mode_custom">"Пользовательские"</string>
|
||||
<string name="screen_room_details_notification_mode_default">"По умолчанию"</string>
|
||||
<string name="screen_room_details_notification_title">"Уведомления"</string>
|
||||
<string name="screen_room_details_pinned_events_row_title">"Закрепленные сообщения"</string>
|
||||
<string name="screen_room_details_pinned_events_row_title">"Закреплённые сообщения"</string>
|
||||
<string name="screen_room_details_profile_row_title">"Профиль"</string>
|
||||
<string name="screen_room_details_requests_to_join_title">"Запросы на вступление"</string>
|
||||
<string name="screen_room_details_roles_and_permissions">"Роли и разрешения"</string>
|
||||
@@ -113,8 +113,8 @@
|
||||
<string name="screen_room_notification_settings_default_setting_title">"Настройка по умолчанию"</string>
|
||||
<string name="screen_room_notification_settings_edit_remove_setting">"Удалить пользовательскую настройку"</string>
|
||||
<string name="screen_room_notification_settings_error_loading_settings">"Произошла ошибка при загрузке настроек уведомлений."</string>
|
||||
<string name="screen_room_notification_settings_error_restoring_default">"Не удалось восстановить режим по умолчанию, попробуйте еще раз."</string>
|
||||
<string name="screen_room_notification_settings_error_setting_mode">"Не удалось настроить режим, попробуйте еще раз."</string>
|
||||
<string name="screen_room_notification_settings_error_restoring_default">"Не удалось восстановить режим по умолчанию, попробуйте ещё раз."</string>
|
||||
<string name="screen_room_notification_settings_error_setting_mode">"Не удалось настроить режим, попробуйте ещё раз."</string>
|
||||
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ваш домашний сервер не поддерживает эту опцию в зашифрованных комнатах, вы не будете получать уведомления в этой комнате."</string>
|
||||
<string name="screen_room_notification_settings_mode_all_messages">"О всех сообщениях"</string>
|
||||
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Только упоминания и ключевые слова"</string>
|
||||
@@ -153,7 +153,7 @@
|
||||
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Любой желающий может присоединиться"</string>
|
||||
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Кто угодно"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer">"Выберите, участники каких пространств могут присоединиться к этой комнате без приглашения.%1$s"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer_manage_spaces_action">"Управление пространством"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer_manage_spaces_action">"Управление пространствами"</string>
|
||||
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Присоединиться могут только приглашенные люди."</string>
|
||||
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Только по приглашению"</string>
|
||||
<string name="screen_security_and_privacy_room_access_section_header">"Доступ"</string>
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ interface RoomMemberModerationRenderer {
|
||||
fun Render(
|
||||
state: RoomMemberModerationState,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit,
|
||||
onAvatarClick: ((MatrixUser) -> Unit)?,
|
||||
modifier: Modifier,
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -25,10 +25,11 @@ class DefaultRoomMemberModerationRenderer : RoomMemberModerationRenderer {
|
||||
override fun Render(
|
||||
state: RoomMemberModerationState,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit,
|
||||
onAvatarClick: ((MatrixUser) -> Unit)?,
|
||||
modifier: Modifier
|
||||
) {
|
||||
if (state is InternalRoomMemberModerationState) {
|
||||
RoomMemberModerationView(state, onSelectAction, modifier)
|
||||
RoomMemberModerationView(modifier = modifier, state = state, onSelectAction = onSelectAction, onAvatarClick = onAvatarClick)
|
||||
} else {
|
||||
SideEffect {
|
||||
Timber.d("RoomMemberModerationRenderer: Render called with unsupported state: $state")
|
||||
|
||||
+17
-10
@@ -12,6 +12,7 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
@@ -64,6 +65,7 @@ import timber.log.Timber
|
||||
fun RoomMemberModerationView(
|
||||
state: InternalRoomMemberModerationState,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit,
|
||||
onAvatarClick: ((MatrixUser) -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(modifier = modifier) {
|
||||
@@ -73,6 +75,7 @@ fun RoomMemberModerationView(
|
||||
user = selectedUser,
|
||||
actions = state.actions,
|
||||
onSelectAction = onSelectAction,
|
||||
onAvatarClick = onAvatarClick,
|
||||
onDismiss = { state.eventSink(InternalRoomMemberModerationEvents.Reset) },
|
||||
)
|
||||
}
|
||||
@@ -214,6 +217,7 @@ private fun RoomMemberActionsBottomSheet(
|
||||
user: MatrixUser,
|
||||
actions: ImmutableList<ModerationActionState>,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit,
|
||||
onAvatarClick: ((MatrixUser) -> Unit)? = null,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
@@ -240,10 +244,11 @@ private fun RoomMemberActionsBottomSheet(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 24.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.clickable {
|
||||
.clickable(enabled = user.avatarUrl != null && onAvatarClick != null) {
|
||||
coroutineScope.launch {
|
||||
onSelectAction(ModerationAction.DisplayProfile, user)
|
||||
bottomSheetState.hide()
|
||||
onAvatarClick?.invoke(user)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -282,8 +287,8 @@ private fun RoomMemberActionsBottomSheet(
|
||||
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())),
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
onSelectAction(action, user)
|
||||
bottomSheetState.hide()
|
||||
onSelectAction(action, user)
|
||||
}
|
||||
},
|
||||
enabled = actionState.isEnabled
|
||||
@@ -340,16 +345,18 @@ private fun RoomMemberActionsBottomSheet(
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun RoomMemberModerationViewPreview(@PreviewParameter(InternalRoomMemberModerationStateProvider::class) state: InternalRoomMemberModerationState) {
|
||||
val isDoingAction = listOf(state.kickUserAsyncAction, state.banUserAsyncAction, state.unbanUserAsyncAction).any { it is AsyncAction.Loading }
|
||||
val modifier = if (isDoingAction) {
|
||||
Modifier.fillMaxWidth().heightIn(min = 64.dp)
|
||||
} else {
|
||||
Modifier.fillMaxSize()
|
||||
}
|
||||
ElementPreview {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 64.dp)
|
||||
) {
|
||||
Box(modifier) {
|
||||
RoomMemberModerationView(
|
||||
state = state,
|
||||
onSelectAction = { _, _ ->
|
||||
},
|
||||
onSelectAction = { _, _ -> },
|
||||
onAvatarClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<string name="screen_bottom_sheet_manage_room_member_banning_user">"Блакіроўка %1$s"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_kick_member_confirmation_description">"Яны змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць."</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_member_user_info">"Прагляд профілю"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_remove">"Выдаліць удзельніка з пакоя"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_remove">"Выдаліць удзельніка"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_remove_confirmation_title">"Выдаліць удзельніка і забараніць далучацца ў будучыні?"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_removing_user">"Выдаленне %1$s…"</string>
|
||||
<string name="screen_bottom_sheet_manage_room_member_unban_member_confirmation_action">"Разблакіраваць"</string>
|
||||
|
||||
+5
@@ -21,6 +21,7 @@ import io.element.android.features.roommembermoderation.api.RoomMemberModeration
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
|
||||
import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
import io.element.android.tests.testutils.clickOn
|
||||
@@ -48,6 +49,8 @@ class RoomMemberModerationViewTest {
|
||||
onSelectAction = callback
|
||||
)
|
||||
clickOn(R.string.screen_bottom_sheet_manage_room_member_member_user_info)
|
||||
// Gives time for bottomsheet to hide
|
||||
mainClock.advanceTimeBy(1_000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,11 +220,13 @@ class RoomMemberModerationViewTest {
|
||||
private fun AndroidComposeUiTest<ComponentActivity>.setRoomMemberModerationView(
|
||||
state: InternalRoomMemberModerationState,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit = EnsureNeverCalledWithTwoParams(),
|
||||
onAvatarClick: ((MatrixUser) -> Unit)? = EnsureNeverCalledWithParam(),
|
||||
) {
|
||||
setSafeContent {
|
||||
RoomMemberModerationView(
|
||||
state = state,
|
||||
onSelectAction = onSelectAction,
|
||||
onAvatarClick = onAvatarClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
<string name="screen_chat_backup_key_storage_toggle_description">"Загрузить ключи с этого устройства"</string>
|
||||
<string name="screen_chat_backup_key_storage_toggle_title">"Разрешить хранение ключей"</string>
|
||||
<string name="screen_chat_backup_recovery_action_change">"Изменить ключ восстановления"</string>
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Если вы потеряли доступ к другим устройствам, то сможете восстановить свою идентификацию и историю сообщений с помощью ключа восстановления."</string>
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Ваши чаты автоматически резервируются с помощью сквозного шифрования. Для восстановления резервной копии и сохранения Вашей цифровой личности в случае потери доступа ко всем устройствам потребуется ключ восстановления."</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm">"Введите ключ восстановления"</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm_description">"В настоящее время резервная копия ваших чатов не синхронизирована."</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Получить ключ восстановления"</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup_description">"Ваши чаты автоматически резервируются с использованием сквозного шифрования. Для восстановления этой резервной копии и сохранения вашей цифровой личности в случае потери доступа ко всем вашим устройствам вам потребуется ключ восстановления."</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_1">"Откройте %1$s на компьютере"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_2">"Войдите в свой аккаунт еще раз"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_2">"Войдите в свой аккаунт ещё раз"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3">"Когда потребуется подтвердить устройство, выберите %1$s"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3_reset_all">"«Сбросить все»"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_4">"Следуйте инструкциям, чтобы создать новый ключ восстановления"</string>
|
||||
@@ -24,7 +24,7 @@
|
||||
<string name="screen_encryption_reset_bullet_1">"Данные вашего аккаунта, контакты, настройки и список чатов будут сохранены"</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"Вы потеряете историю тех сообщений, которые хранятся только на сервере"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Вам нужно будет заново подтвердить все существующие устройства и контакты."</string>
|
||||
<string name="screen_encryption_reset_footer">"Сбрасывайте ключ шифрования только в том случае, если у вас нет доступа к другому устройству, на котором выполнен вход, и вы потеряли ключ восстановления."</string>
|
||||
<string name="screen_encryption_reset_footer">"Сбрасывайте ключ шифрования только в том случае, если у Вас нет доступа к другому устройству, на котором выполнен вход, и Вы потеряли ключ восстановления."</string>
|
||||
<string name="screen_encryption_reset_title">"Не можете подтвердить? Вам потребуется сбросить свою цифровую идентификацию."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Удалить"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Вы потеряете зашифрованные сообщения, если выйдете из всех устройств."</string>
|
||||
@@ -40,9 +40,9 @@
|
||||
<string name="screen_recovery_key_change_title">"Изменить ключ восстановления?"</string>
|
||||
<string name="screen_recovery_key_confirm_create_new_recovery_key">"Создать новый ключ восстановления"</string>
|
||||
<string name="screen_recovery_key_confirm_description">"Убедитесь, что никто не подсматривает)"</string>
|
||||
<string name="screen_recovery_key_confirm_error_content">"Пожалуйста, попробуйте еще раз, чтобы подтвердить доступ к резервной копии чата."</string>
|
||||
<string name="screen_recovery_key_confirm_error_content">"Пожалуйста, попробуйте ещё раз, чтобы подтвердить доступ к резервной копии чата."</string>
|
||||
<string name="screen_recovery_key_confirm_error_title">"Неверный ключ восстановления"</string>
|
||||
<string name="screen_recovery_key_confirm_key_description">"Если у вас есть пароль для восстановления или секретный пароль/ключ, это тоже сработает."</string>
|
||||
<string name="screen_recovery_key_confirm_key_description">"Если у Вас есть ключ/фраза для восстановления, это тоже сработает."</string>
|
||||
<string name="screen_recovery_key_confirm_key_placeholder">"Введите…"</string>
|
||||
<string name="screen_recovery_key_confirm_lost_recovery_key">"Потеряли ключ восстановления?"</string>
|
||||
<string name="screen_recovery_key_confirm_success">"Ключ восстановления подтвержден"</string>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_edit_room_address_title">"Рэдагаваць адрас"</string>
|
||||
<string name="screen_manage_authorized_spaces_your_spaces_section_title">"Вашы прасторы"</string>
|
||||
<string name="screen_security_and_privacy_room_address_section_header">"Адрас"</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<string name="screen_edit_room_address_room_address_section_footer">"Необходимо задать адрес комнаты, чтобы опубликовать ее в каталоге комнат."</string>
|
||||
<string name="screen_edit_room_address_title">"Редактировать адрес комнаты"</string>
|
||||
<string name="screen_manage_authorized_spaces_header">"Пространства, где участники могут присоединиться к комнате без приглашения."</string>
|
||||
<string name="screen_manage_authorized_spaces_title">"Управление пространством"</string>
|
||||
<string name="screen_manage_authorized_spaces_title">"Управление пространствами"</string>
|
||||
<string name="screen_manage_authorized_spaces_unknown_space">"(неизвестное пространство)"</string>
|
||||
<string name="screen_manage_authorized_spaces_unknown_spaces_section_title">"Другие пространства, в которых вы не состоите"</string>
|
||||
<string name="screen_manage_authorized_spaces_your_spaces_section_title">"Ваши пространства"</string>
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Любой желающий может присоединиться"</string>
|
||||
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Кто угодно"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer">"Выберите, участники каких пространств могут присоединиться к этой комнате без приглашения.%1$s"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer_manage_spaces_action">"Управление пространством"</string>
|
||||
<string name="screen_security_and_privacy_room_access_footer_manage_spaces_action">"Управление пространствами"</string>
|
||||
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Присоединиться могут только приглашенные люди."</string>
|
||||
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Только по приглашению"</string>
|
||||
<string name="screen_security_and_privacy_room_access_section_header">"Доступ"</string>
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<string name="screen_signed_out_reason_1">"Вы изменили свой пароль в другой сессии"</string>
|
||||
<string name="screen_signed_out_reason_2">"Вы удалили сессию из другой сессии"</string>
|
||||
<string name="screen_signed_out_reason_3">"Администратор вашего сервера аннулировал ваш доступ"</string>
|
||||
<string name="screen_signed_out_subtitle">"Возможно, вы вышли из системы по одной из причин, перечисленных ниже. Пожалуйста, войдите в систему еще раз, чтобы продолжить использование %s."</string>
|
||||
<string name="screen_signed_out_subtitle">"Возможно, Вы вышли из системы по одной из причин, перечисленных ниже. Пожалуйста, войдите в систему ещё раз, чтобы продолжить использовать %s."</string>
|
||||
<string name="screen_signed_out_title">"Вы вышли из системы"</string>
|
||||
</resources>
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
<string name="screen_identity_use_another_device">"Выкарыстоўвайце іншую прыладу"</string>
|
||||
<string name="screen_identity_waiting_on_other_device">"Чаканне на іншай прыладзе…"</string>
|
||||
<string name="screen_session_verification_cancelled_subtitle">"Здаецца, нешта не так. Альбо час чакання запыту скончыўся, альбо запыт быў адхілены."</string>
|
||||
<string name="screen_session_verification_compare_emojis_subtitle">"Пераканайцеся, што прыведзеныя ніжэй эмодзі супадаюць з эмодзі, паказанымі ў вашым іншым сеансе."</string>
|
||||
<string name="screen_session_verification_compare_emojis_subtitle">"Пераканайцеся, што эмодзі ніжэй супадаюць з тымі, што паказаны на вашай іншай прыладзе."</string>
|
||||
<string name="screen_session_verification_compare_emojis_title">"Параўнайце эмодзі"</string>
|
||||
<string name="screen_session_verification_compare_numbers_subtitle">"Пераканайцеся, што прыведзеныя ніжэй лічбы супадаюць з лічбамі, паказанымі ў іншым сеансе."</string>
|
||||
<string name="screen_session_verification_compare_numbers_title">"Параўнайце лічбы"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Ваш новы сеанс пацверджаны. Ён мае доступ да вашых зашыфраваных паведамленняў, і іншыя карыстальнікі будуць лічыць яго давераным."</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Цяпер вы можаце бяспечна чытаць або адпраўляць паведамленні на іншай прыладзе."</string>
|
||||
<string name="screen_session_verification_device_verified">"Прылада праверана"</string>
|
||||
<string name="screen_session_verification_enter_recovery_key">"Увядзіце ключ аднаўлення"</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Дакажыце, што гэта вы, каб атрымаць доступ да вашай зашыфраванай гісторыі паведамленняў."</string>
|
||||
@@ -25,11 +25,11 @@
|
||||
<string name="screen_session_verification_positive_button_verifying_ongoing">"Чаканне супадзення"</string>
|
||||
<string name="screen_session_verification_ready_subtitle">"Параўнайце ўнікальны набор эмодзі."</string>
|
||||
<string name="screen_session_verification_request_accepted_subtitle">"Параўнайце ўнікальныя эмодзі, пераканаўшыся, што яны размешчаны ў тым жа парадку."</string>
|
||||
<string name="screen_session_verification_request_success_subtitle">"Ваш новы сеанс пацверджаны. Ён мае доступ да вашых зашыфраваных паведамленняў, і іншыя карыстальнікі будуць лічыць яго давераным."</string>
|
||||
<string name="screen_session_verification_request_success_subtitle">"Цяпер вы можаце бяспечна чытаць або адпраўляць паведамленні на іншай прыладзе."</string>
|
||||
<string name="screen_session_verification_request_success_title">"Прылада праверана"</string>
|
||||
<string name="screen_session_verification_they_dont_match">"Яны не супадаюць"</string>
|
||||
<string name="screen_session_verification_they_match">"Яны супадаюць"</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Для працягу працы прыміце запыт на запуск працэсу праверкі ў іншым сеансе."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"Чаканне прыняцця запыту"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выхад…"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Выдаленне прылады…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="screen_identity_confirmation_title">"Подтвердите личность"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Использовать другое устройство"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Использовать ключ восстановления"</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Теперь вы можете безопасно читать и отправлять сообщения, и все, с кем вы общаетесь в чате, также могут доверять этому устройству."</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Теперь Вы можете безопасно читать и отправлять сообщения, и все, с кем Вы общаетесь в чате, также могут доверять этому устройству."</string>
|
||||
<string name="screen_identity_confirmed_title">"Устройство проверено"</string>
|
||||
<string name="screen_identity_use_another_device">"Использовать другое устройство"</string>
|
||||
<string name="screen_identity_waiting_on_other_device">"Ожидание другого устройства…"</string>
|
||||
|
||||
+10
-10
@@ -3,9 +3,9 @@
|
||||
|
||||
[versions]
|
||||
# Project
|
||||
android_gradle_plugin = "8.13.2"
|
||||
android_gradle_plugin = "9.2.1"
|
||||
# When updating this, please also update the version in the file ./idea/kotlinc.xml
|
||||
kotlin = "2.3.21"
|
||||
kotlin = "2.4.0"
|
||||
kotlinpoet = "2.3.0"
|
||||
ksp = "2.3.9"
|
||||
firebaseAppDistribution = "5.2.1"
|
||||
@@ -46,12 +46,12 @@ showkase = "1.0.5"
|
||||
# When upgrading this version, check state restoration still works fine.
|
||||
appyx = "1.7.1"
|
||||
sqldelight = "2.3.2"
|
||||
wysiwyg = "2.41.3"
|
||||
wysiwyg = "2.42.0"
|
||||
telephoto = "0.19.0"
|
||||
haze = "1.7.2"
|
||||
|
||||
# Dependency analysis
|
||||
dependencyAnalysis = "3.14.0"
|
||||
dependencyAnalysis = "3.14.1"
|
||||
|
||||
# DI
|
||||
metro = "1.1.1"
|
||||
@@ -84,7 +84,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin
|
||||
kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" }
|
||||
ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
|
||||
# https://firebase.google.com/docs/android/setup#available-libraries
|
||||
google_firebase_bom = "com.google.firebase:firebase-bom:34.14.0"
|
||||
google_firebase_bom = "com.google.firebase:firebase-bom:34.14.1"
|
||||
firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" }
|
||||
autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" }
|
||||
ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }
|
||||
@@ -183,7 +183,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version
|
||||
# https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt
|
||||
# All new features should not be implemented in the pull request that upgrades the version, developers should
|
||||
# only fix API breaks and may add some TODOs.
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.06.3"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.06.11"
|
||||
|
||||
# Others
|
||||
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
|
||||
@@ -212,7 +212,7 @@ vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0"
|
||||
telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil3", version.ref = "telephoto" }
|
||||
telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" }
|
||||
statemachine = "com.freeletics.flowredux:compose:1.2.2"
|
||||
maplibre = "org.maplibre.gl:android-sdk:13.2.0"
|
||||
maplibre = "org.maplibre.gl:android-sdk:13.3.0"
|
||||
maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2"
|
||||
maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.0"
|
||||
maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2"
|
||||
@@ -227,7 +227,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0"
|
||||
|
||||
# Analytics
|
||||
posthog = "com.posthog:posthog-android:3.47.0"
|
||||
sentry = "io.sentry:sentry-android:8.41.0"
|
||||
sentry = "io.sentry:sentry-android:8.43.1"
|
||||
# main branch can be tested replacing the version with main-SNAPSHOT
|
||||
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.36.1"
|
||||
|
||||
@@ -269,11 +269,11 @@ ktlint = "org.jlleitschuh.gradle.ktlint:14.2.0"
|
||||
dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12"
|
||||
dependencycheck = "org.owasp.dependencycheck:12.2.2"
|
||||
dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" }
|
||||
paparazzi = "app.cash.paparazzi:2.0.0-alpha04"
|
||||
paparazzi = "app.cash.paparazzi:2.0.0-alpha05"
|
||||
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
|
||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
||||
firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" }
|
||||
sonarqube = "org.sonarqube:7.3.0.8198"
|
||||
sonarqube = "org.sonarqube:7.3.1.8318"
|
||||
licensee = "app.cash.licensee:1.14.1"
|
||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
gms_google_services = { id = "com.google.gms.google-services", version = "4.4.4" }
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 318 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 595 KiB |
@@ -27,7 +27,7 @@
|
||||
<string name="state_event_room_invite_accepted">"%1$s принял(а) приглашение"</string>
|
||||
<string name="state_event_room_invite_accepted_by_you">"Вы приняли приглашение"</string>
|
||||
<string name="state_event_room_invite_by_you">"Вы пригласили %1$s"</string>
|
||||
<string name="state_event_room_invite_you">"%1$s пригласил(а) вас"</string>
|
||||
<string name="state_event_room_invite_you">"%1$s пригласил(а) Вас"</string>
|
||||
<string name="state_event_room_join">"%1$s присоединился(ась)"</string>
|
||||
<string name="state_event_room_join_by_you">"Вы присоединились к комнате"</string>
|
||||
<string name="state_event_room_knock">"%1$s хочет присоединиться"</string>
|
||||
@@ -47,8 +47,8 @@
|
||||
<string name="state_event_room_name_removed_by_you">"Вы удалили название"</string>
|
||||
<string name="state_event_room_none">"%1$s не внес(ла) изменений"</string>
|
||||
<string name="state_event_room_none_by_you">"Вы не внесли изменений"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s изменил(а) закрепленные сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Вы изменили закрепленные сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s изменил(а) закреплённые сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Вы изменили закреплённые сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s закрепил(а) сообщение"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Вы закрепили сообщение"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s открепил(а) сообщение"</string>
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ sealed class ClientException(message: String, val details: String?, cause: Throw
|
||||
details = details,
|
||||
cause = cause
|
||||
)
|
||||
class ContentScanner(message: String, val reason: ContentScannerErrorReason) : ClientException(message, null, null)
|
||||
class Other(message: String, cause: Throwable? = null) : ClientException(message, null, cause)
|
||||
}
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.exception
|
||||
|
||||
enum class ContentScannerErrorReason {
|
||||
MCS_MALFORMED_JSON,
|
||||
MCS_MEDIA_FAILED_TO_DECRYPT,
|
||||
M_MISSING_TOKEN,
|
||||
M_UNKNOWN_TOKEN,
|
||||
M_NOT_FOUND,
|
||||
MCS_MEDIA_NOT_CLEAN,
|
||||
MCS_MIME_TYPE_FORBIDDEN,
|
||||
MCS_BAD_DECRYPTION,
|
||||
M_UNKNOWN,
|
||||
MCS_MEDIA_REQUEST_FAILED;
|
||||
|
||||
companion object;
|
||||
|
||||
fun isDangerous(): Boolean = when (this) {
|
||||
MCS_MEDIA_NOT_CLEAN, MCS_MIME_TYPE_FORBIDDEN -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
+5
@@ -9,6 +9,7 @@
|
||||
package io.element.android.libraries.matrix.impl.exception
|
||||
|
||||
import io.element.android.libraries.matrix.api.exception.ClientException
|
||||
import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason
|
||||
import org.matrix.rustcomponents.sdk.ClientException as RustClientException
|
||||
|
||||
fun Throwable.mapClientException(): ClientException {
|
||||
@@ -23,6 +24,10 @@ fun Throwable.mapClientException(): ClientException {
|
||||
details = details,
|
||||
cause = this,
|
||||
)
|
||||
is RustClientException.ContentScanner -> ClientException.ContentScanner(
|
||||
message = message,
|
||||
reason = ContentScannerErrorReason.fromRust(reason),
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> ClientException.Other(message ?: "Unknown error", this)
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.exception
|
||||
|
||||
import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_BAD_DECRYPTION
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MALFORMED_JSON
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_FAILED_TO_DECRYPT
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_NOT_CLEAN
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_REQUEST_FAILED
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MIME_TYPE_FORBIDDEN
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_MISSING_TOKEN
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_NOT_FOUND
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_UNKNOWN
|
||||
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_UNKNOWN_TOKEN
|
||||
|
||||
fun ContentScannerErrorReason.Companion.fromRust(reason: ErrorReason) = when (reason) {
|
||||
M_UNKNOWN -> ContentScannerErrorReason.M_UNKNOWN
|
||||
M_MISSING_TOKEN -> ContentScannerErrorReason.M_MISSING_TOKEN
|
||||
M_UNKNOWN_TOKEN -> ContentScannerErrorReason.M_UNKNOWN_TOKEN
|
||||
MCS_MALFORMED_JSON -> ContentScannerErrorReason.MCS_MALFORMED_JSON
|
||||
MCS_MEDIA_FAILED_TO_DECRYPT -> ContentScannerErrorReason.MCS_MEDIA_FAILED_TO_DECRYPT
|
||||
M_NOT_FOUND -> ContentScannerErrorReason.M_NOT_FOUND
|
||||
MCS_MEDIA_NOT_CLEAN -> ContentScannerErrorReason.MCS_MEDIA_NOT_CLEAN
|
||||
MCS_MIME_TYPE_FORBIDDEN -> ContentScannerErrorReason.MCS_MIME_TYPE_FORBIDDEN
|
||||
MCS_BAD_DECRYPTION -> ContentScannerErrorReason.MCS_BAD_DECRYPTION
|
||||
MCS_MEDIA_REQUEST_FAILED -> ContentScannerErrorReason.MCS_MEDIA_REQUEST_FAILED
|
||||
}
|
||||
+4
@@ -51,6 +51,10 @@ class RustLinkMobileHandler(
|
||||
)
|
||||
// We emit Done in case the progress listener was deallocated before generate() sent the Done
|
||||
_linkMobileStep.emit(LinkMobileStep.Done)
|
||||
} catch (e: HumanQrGrantLoginException.Expired) {
|
||||
// Note: the SDK does not return this error, but is returning `.NotFound` instead when the QR code expires. We catch both just in case.
|
||||
Timber.tag(tag.value).w(e, "QR code has expired")
|
||||
_linkMobileStep.emit(LinkMobileStep.QrRotating)
|
||||
} catch (e: HumanQrGrantLoginException.NotFound) {
|
||||
Timber.tag(tag.value).w(e, "Error during QR login grant")
|
||||
// Catch timeout here?
|
||||
|
||||
+26
@@ -147,6 +147,32 @@ class RustLinkMobileHandlerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when start throws HumanQrGrantLoginException_Expired, the handler emits QrRotating step`() = runTest {
|
||||
val completable = CompletableDeferred<Unit>()
|
||||
val handler = FakeFfiGrantLoginWithQrCodeHandler(
|
||||
generateResult = {
|
||||
completable.await()
|
||||
throw HumanQrGrantLoginException.Expired("Expired")
|
||||
}
|
||||
)
|
||||
val sut = createRustLinkMobileHandler(
|
||||
handler,
|
||||
)
|
||||
sut.linkMobileStep.test {
|
||||
val initialItem = awaitItem()
|
||||
assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized)
|
||||
backgroundScope.launch {
|
||||
sut.start()
|
||||
}
|
||||
runCurrent()
|
||||
// generate returns, error is emitted
|
||||
completable.complete(Unit)
|
||||
val qrRotatingState = awaitItem()
|
||||
assertThat(qrRotatingState).isEqualTo(LinkMobileStep.QrRotating)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createRustLinkMobileHandler(
|
||||
handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(),
|
||||
) = RustLinkMobileHandler(
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ fun SpaceRoomItemView(
|
||||
indication = ripple(),
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
)
|
||||
.onKeyboardContextMenuAction { onLongClick }
|
||||
.onKeyboardContextMenuAction(onLongClick)
|
||||
Column(
|
||||
modifier = modifier
|
||||
.then(clickModifier)
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
<string name="screen_bottom_sheet_create_dm_title">"Отправить приглашение?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_content">"У Вас нет других чатов с этим пользователем. Подтвердите, что это действительно кого Вы хотите пригласить, прежде чем продолжить."</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_title">"Начать чат с этим новым контактом?"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) вас"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) пригласил(а) Вас"</string>
|
||||
</resources>
|
||||
|
||||
+1
-1
@@ -258,7 +258,7 @@ class ExoPlayerForPreview(
|
||||
override fun setPriorityTaskManager(priorityTaskManager: PriorityTaskManager?) {}
|
||||
override fun isSleepingForOffload(): Boolean = throw NotImplementedError()
|
||||
override fun isTunnelingEnabled(): Boolean = throw NotImplementedError()
|
||||
override fun isReleased(): Boolean = throw NotImplementedError()
|
||||
override fun isReleased(): Boolean = false
|
||||
override fun setImageOutput(imageOutput: ImageOutput?) {}
|
||||
override fun setAudioCodecParameters(codecParameters: CodecParameters) {}
|
||||
override fun addAudioCodecParametersChangeListener(listener: CodecParametersChangeListener, keys: List<String>) {}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_media_details_title">"Інфармацыя пра файл"</string>
|
||||
</resources>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user