diff --git a/CHANGES.md b/CHANGES.md
index ae9e428795..acf41b40e6 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,31 +2,44 @@ Changes in Element 1.0.6 (2020-XX-XX)
===================================================
Features ✨:
- -
+ - List phone numbers and emails added to the Matrix account, and add emails and phone numbers to account (#44, #45)
Improvements 🙌:
- You can now join room through permalink and within room directory search
- Add long click gesture to copy userId, user display name, room name, room topic and room alias (#1774)
+ - Fix several issues when uploading bug files (#1889)
+ - Do not propose to verify session if there is only one session and 4S is not configured (#1901)
+ - Call screen does not use proximity sensor (#1735)
Bugfix 🐛:
- Display name not shown under Settings/General (#1926)
+ - Editing message forgets line breaks and markdown (#1939)
- Words containing my name should not trigger notifications (#1781)
- Fix changing language issue
- Fix FontSize issue (#1483, #1787)
- Fix bad color for settings icon on Android < 24 (#1786)
- Change user or room avatar: when selecting Gallery, I'm not proposed to crop the selected image (#1590)
+ - Loudspeaker is always used (#1685)
- Fix uploads still don't work with room v6 (#1879)
- Can't handle ongoing call events in background (#1992)
- Handle room, user and group links by the Element app (#1795)
+ - Crash / Attachment viewer: Cannot draw a recycled Bitmap #2034
+ - Login with Matrix-Id | Autodiscovery fails if identity server is invalid and Homeserver ok (#2027)
+ - Support for image compression on Android 10
+ - Verification popup won't show
Translations 🗣:
- -
+ - The SDK is now using SAS string translations from [Weblate Matrix-doc project](https://translate.riot.im/projects/matrix-doc/) (#1909)
SDK API changes ⚠️:
-
Build 🧱:
- Some dependencies have been upgraded (coroutine, recyclerView, appCompat, core-ktx, firebase-messaging)
+ - Buildkite:
+ New pipeline location: https://github.com/matrix-org/pipelines/blob/master/element-android/pipeline.yml
+ New build location: https://buildkite.com/matrix-dot-org/element-android
+
Other changes:
- Use File extension functions to make code more concise (#1996)
diff --git a/README.md b/README.md
index 9f31e83ef6..64c6c9d04d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
+[](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
[](https://translate.riot.im/engage/element-android/?utm_source=widget)
[](https://matrix.to/#/#element-android:matrix.org)
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
@@ -14,7 +14,7 @@ It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-androi
[](https://play.google.com/store/apps/details?id=im.vector.app)
[](https://f-droid.org/app/im.vector.app)
-Nightly build: [](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
+Nightly build: [](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
# New Android SDK
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AnimatedImageViewHolder.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AnimatedImageViewHolder.kt
index 6b7818c612..96e6c92467 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AnimatedImageViewHolder.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AnimatedImageViewHolder.kt
@@ -27,4 +27,9 @@ class AnimatedImageViewHolder constructor(itemView: View) :
val imageLoaderProgress: ProgressBar = itemView.findViewById(R.id.imageLoaderProgress)
internal val target = DefaultImageLoaderTarget(this, this.touchImageView)
+
+ override fun onRecycled() {
+ super.onRecycled()
+ touchImageView.setImageDrawable(null)
+ }
}
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
index 1e5e88d91f..9166c2ce4f 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
@@ -50,6 +50,7 @@ internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, pri
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
if (holder.boundResourceUid != uid) return
holder.imageLoaderProgress.isVisible = false
+ holder.touchImageView.setImageDrawable(errorDrawable)
}
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
@@ -77,11 +78,13 @@ internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, pri
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
if (holder.boundResourceUid != uid) return
holder.imageLoaderProgress.isVisible = true
+ holder.touchImageView.setImageDrawable(placeholder)
}
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
if (holder.boundResourceUid != uid) return
holder.imageLoaderProgress.isVisible = false
+ holder.touchImageView.setImageDrawable(errorDrawable)
}
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoLoaderTarget.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoLoaderTarget.kt
index 78f46a320f..d88faba110 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoLoaderTarget.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoLoaderTarget.kt
@@ -35,6 +35,7 @@ interface VideoLoaderTarget {
fun onVideoFileLoading(uid: String)
fun onVideoFileLoadFailed(uid: String)
fun onVideoFileReady(uid: String, file: File)
+ fun onVideoURLReady(uid: String, path: String)
}
internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val contextView: ImageView) : VideoLoaderTarget {
@@ -47,6 +48,8 @@ internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val
}
override fun onThumbnailResourceCleared(uid: String, placeholder: Drawable?) {
+ if (holder.boundResourceUid != uid) return
+ holder.thumbnailImage.setImageDrawable(placeholder)
}
override fun onThumbnailResourceReady(uid: String, resource: Drawable) {
@@ -68,9 +71,19 @@ internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val
override fun onVideoFileReady(uid: String, file: File) {
if (holder.boundResourceUid != uid) return
+ arrangeForVideoReady()
+ holder.videoReady(file)
+ }
+
+ override fun onVideoURLReady(uid: String, path: String) {
+ if (holder.boundResourceUid != uid) return
+ arrangeForVideoReady()
+ holder.videoReady(path)
+ }
+
+ private fun arrangeForVideoReady() {
holder.thumbnailImage.isVisible = false
holder.loaderProgressBar.isVisible = false
holder.videoView.isVisible = true
- holder.videoReady(file)
}
}
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
index 32f449d6fe..4d8be6468b 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
@@ -16,6 +16,7 @@
package im.vector.lib.attachmentviewer
+import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar
@@ -65,6 +66,13 @@ class VideoViewHolder constructor(itemView: View) :
}
}
+ fun videoReady(path: String) {
+ mVideoPath = path
+ if (isSelected) {
+ startPlaying()
+ }
+ }
+
fun videoFileLoadError() {
}
@@ -118,8 +126,13 @@ class VideoViewHolder constructor(itemView: View) :
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
}
}
+ try {
+ videoView.setVideoPath(mVideoPath)
+ } catch (failure: Throwable) {
+ // Couldn't open
+ Log.v(VideoViewHolder::class.java.name, "Failed to start video")
+ }
- videoView.setVideoPath(mVideoPath)
if (!wasPaused) {
videoView.start()
if (progress > 0) {
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ZoomableImageViewHolder.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ZoomableImageViewHolder.kt
index 019cd3202d..49378631e8 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ZoomableImageViewHolder.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ZoomableImageViewHolder.kt
@@ -39,4 +39,9 @@ class ZoomableImageViewHolder constructor(itemView: View) :
}
internal val target = DefaultImageLoaderTarget.ZoomableImageTarget(this, touchImageView)
+
+ override fun onRecycled() {
+ super.onRecycled()
+ touchImageView.setImageDrawable(null)
+ }
}
diff --git a/build.gradle b/build.gradle
index 061dd73a40..f06d1859b5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -87,7 +87,7 @@ sonarqube {
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
property "sonar.sourceEncoding", "UTF-8"
property "sonar.links.homepage", "https://github.com/vector-im/element-android/"
- property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/riotx-android"
+ property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/element-android"
property "sonar.links.scm", "https://github.com/vector-im/element-android/"
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
property "sonar.organization", "new_vector_ltd_organization"
diff --git a/docs/add_threePids.md b/docs/add_threePids.md
new file mode 100644
index 0000000000..89fc92f329
--- /dev/null
+++ b/docs/add_threePids.md
@@ -0,0 +1,285 @@
+# Adding and removing ThreePids to an account
+
+## Add email
+
+### User enter the email
+
+> POST https://homeserver.org/_matrix/client/r0/account/3pid/email/requestToken
+
+```json
+{
+ "email": "alice@email-provider.org",
+ "client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh",
+ "send_attempt": 1
+}
+```
+
+#### The email is already added to an account
+
+400
+
+```json
+{
+ "errcode": "M_THREEPID_IN_USE",
+ "error": "Email is already in use"
+}
+```
+
+#### The email is free
+
+Wording: "We've sent you an email to verify your address. Please follow the instructions there and then click the button below."
+
+200
+
+```json
+{
+ "sid": "bxyDHuJKsdkjMlTJ"
+}
+```
+
+## User receive an e-mail
+
+> [homeserver.org] Validate your email
+>
+> A request to add an email address to your Matrix account has been received. If this was you, please click the link below to confirm adding this email:
+ https://homeserver.org/_matrix/client/unstable/add_threepid/email/submit_token?token=WUnEhQAmJrXupdEbXgdWvnVIKaGYZFsU&client_secret=TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh&sid=bxyDHuJKsdkjMlTJ
+>
+> If this was not you, you can safely ignore this email. Thank you.
+
+### User clicks on the link
+
+The browser displays the following message:
+
+> Your email has now been validated, please return to your client. You may now close this window.
+
+### User returns on Element
+
+User clicks on CONTINUE
+
+> POST https://homeserver.org/_matrix/client/r0/account/3pid/add
+
+```json
+{
+ "sid": "bxyDHuJKsdkjMlTJ",
+ "client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh"
+}
+```
+
+401 User Interactive Authentication
+
+```json
+{
+ "session": "ppvvnozXCQZFaggUBlHJYPjA",
+ "flows": [
+ {
+ "stages": [
+ "m.login.password"
+ ]
+ }
+ ],
+ "params": {
+ }
+}
+```
+
+### User enters his password
+
+POST https://homeserver.org/_matrix/client/r0/account/3pid/add
+
+```json
+{
+ "sid": "bxyDHuJKsdkjMlTJ",
+ "client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh",
+ "auth": {
+ "session": "ppvvnozXCQZFaggUBlHJYPjA",
+ "type": "m.login.password",
+ "user": "@benoitx:matrix.org",
+ "password": "weak_password"
+ }
+}
+```
+
+#### The link has not been clicked
+
+400
+
+```json
+{
+ "errcode": "M_THREEPID_AUTH_FAILED",
+ "error": "No validated 3pid session found"
+}
+```
+
+#### Wrong password
+
+401
+
+```json
+{
+ "session": "fXHOvoQsPMhEebVqTnIrzZJN",
+ "flows": [
+ {
+ "stages": [
+ "m.login.password"
+ ]
+ }
+ ],
+ "params": {
+ },
+ "completed":[
+ ],
+ "error": "Invalid password",
+ "errcode": "M_FORBIDDEN"
+}
+```
+
+#### The link has been clicked and the account password is correct
+
+200
+
+```json
+{}
+```
+
+## Remove email
+
+### User want to remove an email from his account
+
+> POST https://homeserver.org/_matrix/client/r0/account/3pid/delete
+
+```json
+{
+ "medium": "email",
+ "address": "alice@email-provider.org"
+}
+```
+
+#### Email was not bound to an identity server
+
+200
+
+```json
+{
+ "id_server_unbind_result": "no-support"
+}
+```
+
+#### Email was bound to an identity server
+
+200
+
+```json
+{
+ "id_server_unbind_result": "success"
+}
+```
+
+## Add phone number
+
+> POST https://homeserver.org/_matrix/client/r0/account/3pid/msisdn/requestToken
+
+```json
+{
+ "country": "FR",
+ "phone_number": "611223344",
+ "client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
+ "send_attempt": 1
+}
+```
+
+Note that the phone number is sent without `+` and without the country code
+
+#### The phone number is already added to an account
+
+400
+
+```json
+{
+ "errcode": "M_THREEPID_IN_USE",
+ "error": "MSISDN is already in use"
+}
+```
+
+#### The phone number is free
+
+Wording: "A text message has been sent to +33611223344. Please enter the verification code it contains."
+
+200
+
+```json
+{
+ "msisdn": "33651547677",
+ "intl_fmt": "+33 6 51 54 76 77",
+ "success": true,
+ "sid": "253299954",
+ "submit_url": "https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token"
+}
+```
+
+## User receive a text message
+
+> Riot
+
+> Your Riot validation code is 892541, please enter this into the app
+
+### User enter the code to the app
+
+#### Wrong code
+
+> POST https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token
+
+```json
+{
+ "sid": "253299954",
+ "client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
+ "token": "111111"
+}
+```
+
+400
+
+```json
+{
+ "errcode": "M_UNKNOWN",
+ "error": "Error contacting the identity server"
+}
+```
+
+This is not an ideal, but the client will display a hint to check the entered code to the user.
+
+#### Correct code
+
+> POST https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token
+
+```json
+{
+ "sid": "253299954",
+ "client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
+ "token": "892541"
+}
+```
+
+200
+
+```json
+{
+ "success": true
+}
+```
+
+Then the app call `https://homeserver.org/_matrix/client/r0/account/3pid/add` as per adding an email and follow the same UIS flow
+
+## Remove phone number
+
+### User wants to remove a phone number from his account
+
+This is the same request and response than to remove email, but with this body:
+
+```json
+{
+ "medium": "msisdn",
+ "address": "33611223344"
+}
+```
+
+Note that the phone number is provided without `+`, but with the country code.
diff --git a/docs/signin.md b/docs/signin.md
index f5ec03e708..06f715c46b 100644
--- a/docs/signin.md
+++ b/docs/signin.md
@@ -8,7 +8,9 @@ This document describes the flow of signin to a homeserver, and also the flow wh
Client request the sign-in flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
-> curl -X GET 'https://matrix.org/_matrix/client/r0/login'
+```shell script
+curl -X GET 'https://matrix.org/_matrix/client/r0/login'
+```
200
@@ -26,7 +28,9 @@ Client request the sign-in flows, once the homeserver is chosen by the user and
The user is able to connect using `m.login.password`
-> curl -X POST --data $'{"identifier":{"type":"m.id.user","user":"alice"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
+```shell script
+curl -X POST --data $'{"identifier":{"type":"m.id.user","user":"alice"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
+```
```json
{
@@ -73,14 +77,16 @@ We get credential (200)
If the user has associated an email with its account, he can signin using the email.
-> curl -X POST --data $'{"identifier":{"type":"m.id.thirdparty","medium":"email","address":"alice@yopmail.com"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
+```shell script
+curl -X POST --data $'{"identifier":{"type":"m.id.thirdparty","medium":"email","address":"alice@email-provider.org"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
+```
```json
{
"identifier": {
"type": "m.id.thirdparty",
"medium": "email",
- "address": "alice@yopmail.com"
+ "address": "alice@email-provider.org"
},
"password": "weak_password",
"type": "m.login.password",
@@ -136,7 +142,9 @@ Not supported yet in Element
### Login with SSO
-> curl -X GET 'https://homeserver.with.sso/_matrix/client/r0/login'
+```shell script
+curl -X GET 'https://homeserver.with.sso/_matrix/client/r0/login'
+```
200
@@ -171,7 +179,9 @@ Once the process is finished, the web page will call the `redirectUrl` with an e
This navigation is intercepted by Element by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
-> curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
+```shell script
+curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
+```
```json
{
@@ -214,7 +224,9 @@ We display a warning regarding e2e.
At the first step, we do not send the password, only the email and a client secret, generated by the application
-> curl -X POST --data $'{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","send_attempt":0,"email":"user@domain.com"}' 'https://matrix.org/_matrix/client/r0/account/password/email/requestToken'
+```shell script
+curl -X POST --data $'{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","send_attempt":0,"email":"user@domain.com"}' 'https://matrix.org/_matrix/client/r0/account/password/email/requestToken'
+```
```json
{
@@ -251,7 +263,9 @@ During this step, the new password is sent to the homeserver.
If the user confirms before the link is clicked, we get an error:
-> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
+```shell script
+curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
+```
```json
{
@@ -285,7 +299,9 @@ It contains the client secret, a token and the sid
When the user click the link, if validate his ownership and the new password can now be ent by the application (on user demand):
-> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
+```shell script
+curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
+```
```json
{
diff --git a/docs/signup.md b/docs/signup.md
index 995f5d50a6..97cd20a423 100644
--- a/docs/signup.md
+++ b/docs/signup.md
@@ -10,7 +10,9 @@ This document describes the flow of registration to a homeserver. Examples come
Client request the sign-up flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
-> curl -X POST --data $'{}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -70,7 +72,9 @@ If the registration is not possible, we get a 403
The app is displaying a form to enter username and password.
-> curl -X POST --data $'{"initial_device_display_name":"Mobile device","username":"alice","password": "weak_password"}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"initial_device_display_name":"Mobile device","username":"alice","password": "weak_password"}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -133,9 +137,11 @@ We get a 400:
### Step 2: entering email
-User is proposed to enter an email. We skip this step.
+User is proposed to enter an email. User skips this step.
-> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.dummy"}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.dummy"}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -189,16 +195,18 @@ User is proposed to enter an email. We skip this step.
}
```
-### Step 2 bis: we enter an email
+### Step 2 bis: user enters an email
We request a token to the homeserver. The `client_secret` is generated by the application
-> curl -X POST --data $'{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","email":"alice@yopmail.com","send_attempt":0}' 'https://matrix.org/_matrix/client/r0/register/email/requestToken'
+```shell script
+curl -X POST --data $'{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","email":"alice@email-provider.org","send_attempt":0}' 'https://matrix.org/_matrix/client/r0/register/email/requestToken'
+```
```json
{
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
- "email": "alice@yopmail.com",
+ "email": "alice@email-provider.org",
"send_attempt": 0
}
```
@@ -213,7 +221,9 @@ We request a token to the homeserver. The `client_secret` is generated by the ap
And
-> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -239,7 +249,9 @@ We get 401 since the email is not validated yet:
The app is now polling on
-> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -254,7 +266,7 @@ The app is now polling on
}
```
-We click on the link received by email `https://matrix.org/_matrix/client/unstable/registration/email/submit_token?token=vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ&client_secret=53e679ea-oRED-ACTED-92b8-3012c49c6cfa&sid=qlBCREDACTEDEtgxD` which contains:
+User clicks on the link received by email `https://matrix.org/_matrix/client/unstable/registration/email/submit_token?token=vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ&client_secret=53e679ea-oRED-ACTED-92b8-3012c49c6cfa&sid=qlBCREDACTEDEtgxD` which contains:
- A `token` vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ
- The `client_secret`: 53e679ea-oRED-ACTED-92b8-3012c49c6cfa
- A `sid`: qlBCREDACTEDEtgxD
@@ -306,7 +318,9 @@ Once the link is clicked, the registration request (polling) returns a 401 with
User is proposed to accept T&C and he accepts them
-> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.terms"}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.terms"}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -365,7 +379,9 @@ User is proposed to accept T&C and he accepts them
User is proposed to prove he is not a robot and he does it:
-> curl -X POST --data $'{"auth":{"response":"03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q","session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.recaptcha"}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"response":"03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q","session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.recaptcha"}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -396,9 +412,11 @@ Some homeservers may require the user to enter MSISDN.
On matrix.org, it's not required, and not even optional, but it's still possible for the app to add a MSISDN during the registration.
-The user enter a phone number and select a country, the `client_secret` is generated by the application
+The user enters a phone number and selects a country, the `client_secret` is generated by the application
-> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","send_attempt":1,"country":"FR","phone_number":"+33611223344"}' 'https://matrix.org/_matrix/client/r0/register/msisdn/requestToken'
+```shell script
+curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","send_attempt":1,"country":"FR","phone_number":"+33611223344"}' 'https://matrix.org/_matrix/client/r0/register/msisdn/requestToken'
+```
```json
{
@@ -430,10 +448,11 @@ If it is not the case, the homeserver send the SMS and returns some data, especi
}
```
-When you execute the register request, with the received `sid`, you get an error since the MSISDN is not validated yet:
-
-> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
+When we execute the register request, with the received `sid`, we get an error since the MSISDN is not validated yet:
+```shell script
+curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
"auth": {
@@ -492,7 +511,9 @@ There is an issue on Synapse, which return a 401, it sends too much data along w
The user receive the SMS, he can enter the SMS code in the app, which is sent using the "submit_url" received ie the response of the `requestToken` request:
-> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798","token":"123456"}' 'https://matrix.org/_matrix/client/unstable/add_threepid/msisdn/submit_token'
+```shell script
+curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798","token":"123456"}' 'https://matrix.org/_matrix/client/unstable/add_threepid/msisdn/submit_token'
+```
```json
{
@@ -520,7 +541,9 @@ And if the code is correct we get a 200 with:
We can now execute the registration request, to the homeserver
-> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
+```shell script
+curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
+```
```json
{
@@ -535,7 +558,7 @@ We can now execute the registration request, to the homeserver
}
```
-Now the homeserver consider that the `m.login.msisdn` step is completed (401):
+Now the homeserver considers that the `m.login.msisdn` step is completed (401):
```json
{
diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
index 45efd125ee..55ede52c0c 100644
--- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
+++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
@@ -18,9 +18,13 @@
package org.matrix.android.sdk.rx
import androidx.paging.PagedList
+import io.reactivex.Observable
+import io.reactivex.Single
+import io.reactivex.functions.Function3
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@@ -43,10 +47,6 @@ import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
-import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
-import io.reactivex.Observable
-import io.reactivex.Single
-import io.reactivex.functions.Function3
class RxSession(private val session: Session) {
@@ -110,6 +110,11 @@ class RxSession(private val session: Session) {
.startWithCallable { session.getThreePids() }
}
+ fun livePendingThreePIds(): Observable> {
+ return session.getPendingThreePidsLive().asObservable()
+ .startWithCallable { session.getPendingThreePids() }
+ }
+
fun createRoom(roomParams: CreateRoomParams): Single = singleBuilder {
session.createRoom(roomParams, it)
}
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 90bdf02243..2c20137647 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -115,7 +115,7 @@ dependencies {
def coroutines_version = "1.3.8"
def markwon_version = '3.1.0'
def daggerVersion = '2.25.4'
- def work_version = '2.3.3'
+ def work_version = '2.4.0'
def retrofit_version = '2.6.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
@@ -144,7 +144,6 @@ dependencies {
// Image
implementation 'androidx.exifinterface:exifinterface:1.3.0-alpha01'
- implementation 'id.zelory:compressor:3.0.0'
// Database
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
index df359f2adc..df26bb1227 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
@@ -23,15 +23,12 @@ import androidx.work.WorkManager
import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
-import org.matrix.android.sdk.common.DaggerTestMatrixComponent
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
+import org.matrix.android.sdk.common.DaggerTestMatrixComponent
import org.matrix.android.sdk.internal.SessionManager
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
import org.matrix.android.sdk.internal.network.UserAgentHolder
import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.olm.OlmManager
-import java.io.InputStream
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
@@ -96,9 +93,5 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
fun getSdkVersion(): String {
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
}
-
- fun decryptStream(inputStream: InputStream?, elementToDecrypt: ElementToDecrypt): InputStream? {
- return MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
- }
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
index 80e7b6dbbb..1e109f11ae 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
@@ -21,7 +21,6 @@ import android.util.Base64
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertNotNull
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -29,6 +28,8 @@ import org.junit.runners.MethodSorters
import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
+import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
+import java.io.ByteArrayOutputStream
import java.io.InputStream
/**
@@ -52,17 +53,14 @@ class AttachmentEncryptionTest {
memoryFile.inputStream
}
- val decryptedStream = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo)
+ val decryptedStream = ByteArrayOutputStream()
+ val result = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo.toElementToDecrypt()!!, decryptedStream)
- assertNotNull(decryptedStream)
+ assert(result)
- val buffer = ByteArray(100)
+ val toByteArray = decryptedStream.toByteArray()
- val len = decryptedStream!!.read(buffer)
-
- decryptedStream.close()
-
- return Base64.encodeToString(buffer, 0, len, Base64.DEFAULT).replace("\n".toRegex(), "").replace("=".toRegex(), "")
+ return Base64.encodeToString(toByteArray, 0, toByteArray.size, Base64.DEFAULT).replace("\n".toRegex(), "").replace("=".toRegex(), "")
}
@Test
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
index 9b85310d50..eebaa93415 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
@@ -17,23 +17,22 @@
package org.matrix.android.sdk.internal.session.room.send
import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
import org.junit.Assert.assertEquals
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
/**
* It will not be possible to test all combinations. For the moment I add a few tests, then, depending on the problem discovered in the wild,
* we can add more tests to cover the edge cases.
* Some tests are suffixed with `_not_passing`, maybe one day we will fix them...
- * Riot-Web should be used as a reference for expected results, but not always. Especially Riot-Web add lots of `\n` in the
- * formatted body, which is quite useless.
- * Also Riot-Web does not provide plain text body when formatted text is provided. The body contains what the user has entered.
+ * Element Web should be used as a reference for expected results, but not always.
+ * Also Element Web does not provide plain text body when formatted text is provided. The body contains what the user has entered. We are doing
+ * the same to be able to edit messages (See #1939)
* See https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
*/
@Suppress("SpellCheckingInspection")
@@ -46,8 +45,7 @@ class MarkdownParserTest : InstrumentedTest {
*/
private val markdownParser = MarkdownParser(
Parser.builder().build(),
- HtmlRenderer.builder().build(),
- TextContentRenderer.builder().build()
+ HtmlRenderer.builder().build()
)
@Test
@@ -83,6 +81,15 @@ class MarkdownParserTest : InstrumentedTest {
)
}
+ @Test
+ fun parseBoldNewLines() {
+ testTypeNewLines(
+ name = "bold",
+ markdownPattern = "**",
+ htmlExpectedTag = "strong"
+ )
+ }
+
@Test
fun parseItalic() {
testType(
@@ -92,14 +99,23 @@ class MarkdownParserTest : InstrumentedTest {
)
}
+ @Test
+ fun parseItalicNewLines() {
+ testTypeNewLines(
+ name = "italic",
+ markdownPattern = "*",
+ htmlExpectedTag = "em"
+ )
+ }
+
@Test
fun parseItalic2() {
- // Riot-Web format
- "_italic_".let { markdownParser.parse(it) }.expect("italic", "italic")
+ // Element Web format
+ "_italic_".let { markdownParser.parse(it).expect(it, "italic") }
}
/**
- * Note: the test is not passing, it does not work on Riot-Web neither
+ * Note: the test is not passing, it does not work on Element Web neither
*/
@Test
fun parseStrike_not_passing() {
@@ -110,14 +126,30 @@ class MarkdownParserTest : InstrumentedTest {
)
}
+ @Test
+ fun parseStrikeNewLines() {
+ testTypeNewLines(
+ name = "strike",
+ markdownPattern = "~~",
+ htmlExpectedTag = "del"
+ )
+ }
+
@Test
fun parseCode() {
testType(
name = "code",
markdownPattern = "`",
- htmlExpectedTag = "code",
- plainTextPrefix = "\"",
- plainTextSuffix = "\""
+ htmlExpectedTag = "code"
+ )
+ }
+
+ @Test
+ fun parseCodeNewLines() {
+ testTypeNewLines(
+ name = "code",
+ markdownPattern = "`",
+ htmlExpectedTag = "code"
)
}
@@ -126,9 +158,16 @@ class MarkdownParserTest : InstrumentedTest {
testType(
name = "code",
markdownPattern = "``",
- htmlExpectedTag = "code",
- plainTextPrefix = "\"",
- plainTextSuffix = "\""
+ htmlExpectedTag = "code"
+ )
+ }
+
+ @Test
+ fun parseCode2NewLines() {
+ testTypeNewLines(
+ name = "code",
+ markdownPattern = "``",
+ htmlExpectedTag = "code"
)
}
@@ -137,78 +176,85 @@ class MarkdownParserTest : InstrumentedTest {
testType(
name = "code",
markdownPattern = "```",
- htmlExpectedTag = "code",
- plainTextPrefix = "\"",
- plainTextSuffix = "\""
+ htmlExpectedTag = "code"
+ )
+ }
+
+ @Test
+ fun parseCode3NewLines() {
+ testTypeNewLines(
+ name = "code",
+ markdownPattern = "```",
+ htmlExpectedTag = "code"
)
}
@Test
fun parseUnorderedList() {
- "- item1".let { markdownParser.parse(it).expect(it, "
") }
}
private fun testIdentity(text: String) {
@@ -217,59 +263,93 @@ class MarkdownParserTest : InstrumentedTest {
private fun testType(name: String,
markdownPattern: String,
- htmlExpectedTag: String,
- plainTextPrefix: String = "",
- plainTextSuffix: String = "") {
+ htmlExpectedTag: String) {
// Test simple case
"$markdownPattern$name$markdownPattern"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix",
- expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag>")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag>")
+ }
// Test twice the same tag
"$markdownPattern$name$markdownPattern and $markdownPattern$name bis$markdownPattern"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix and $plainTextPrefix$name bis$plainTextSuffix",
- expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag> and <$htmlExpectedTag>$name bis$htmlExpectedTag>")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag> and <$htmlExpectedTag>$name bis$htmlExpectedTag>")
+ }
val textBefore = "a"
val textAfter = "b"
// With sticked text before
"$textBefore$markdownPattern$name$markdownPattern"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix",
- expectedFormattedText = "$textBefore<$htmlExpectedTag>$name$htmlExpectedTag>")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "$textBefore<$htmlExpectedTag>$name$htmlExpectedTag>")
+ }
// With text before and space
"$textBefore $markdownPattern$name$markdownPattern"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix",
- expectedFormattedText = "$textBefore <$htmlExpectedTag>$name$htmlExpectedTag>")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "$textBefore <$htmlExpectedTag>$name$htmlExpectedTag>")
+ }
// With sticked text after
"$markdownPattern$name$markdownPattern$textAfter"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix$textAfter",
- expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag>$textAfter")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag>$textAfter")
+ }
// With space and text after
"$markdownPattern$name$markdownPattern $textAfter"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix $textAfter",
- expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag> $textAfter")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag> $textAfter")
+ }
// With sticked text before and text after
"$textBefore$markdownPattern$name$markdownPattern$textAfter"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix$textAfter",
- expectedFormattedText = "a<$htmlExpectedTag>$name$htmlExpectedTag>$textAfter")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "a<$htmlExpectedTag>$name$htmlExpectedTag>$textAfter")
+ }
// With text before and after, with spaces
"$textBefore $markdownPattern$name$markdownPattern $textAfter"
- .let { markdownParser.parse(it) }
- .expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix $textAfter",
- expectedFormattedText = "$textBefore <$htmlExpectedTag>$name$htmlExpectedTag> $textAfter")
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "$textBefore <$htmlExpectedTag>$name$htmlExpectedTag> $textAfter")
+ }
+ }
+
+ private fun testTypeNewLines(name: String,
+ markdownPattern: String,
+ htmlExpectedTag: String) {
+ // With new line inside the block
+ "$markdownPattern$name\n$name$markdownPattern"
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name $name$htmlExpectedTag>")
+ }
+
+ // With new line between two blocks
+ "$markdownPattern$name$markdownPattern\n$markdownPattern$name$markdownPattern"
+ .let {
+ markdownParser.parse(it)
+ .expect(expectedText = it,
+ expectedFormattedText = "<$htmlExpectedTag>$name$htmlExpectedTag><$htmlExpectedTag>$name$htmlExpectedTag>")
+ }
}
private fun TextContent.expect(expectedText: String, expectedFormattedText: String?) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
index 6cd003ddae..aafefa2048 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
@@ -26,13 +26,10 @@ import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.internal.SessionManager
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
import org.matrix.android.sdk.internal.di.DaggerMatrixComponent
import org.matrix.android.sdk.internal.network.UserAgentHolder
import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.olm.OlmManager
-import java.io.InputStream
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
@@ -97,9 +94,5 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
fun getSdkVersion(): String {
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
}
-
- fun decryptStream(inputStream: InputStream?, elementToDecrypt: ElementToDecrypt): InputStream? {
- return MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
- }
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
index a736a4f1be..ec2dfd214c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
@@ -45,7 +45,7 @@ sealed class WellknownResult {
/**
* Inform the user that auto-discovery failed due to invalid/empty data and PROMPT for the parameter.
*/
- object FailPrompt : WellknownResult()
+ data class FailPrompt(val homeServerUrl: String?, val wellKnown: WellKnown?) : WellknownResult()
/**
* Inform the user that auto-discovery did not return any usable URLs. Do not continue further with the current login process.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
index a29e7110e2..a216770939 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
@@ -33,7 +33,7 @@ interface ContentUploadStateTracker {
object Idle : State()
object EncryptingThumbnail : State()
data class UploadingThumbnail(val current: Long, val total: Long) : State()
- object Encrypting : State()
+ data class Encrypting(val current: Long, val total: Long) : State()
data class Uploading(val current: Long, val total: Long) : State()
object Success : State()
data class Failure(val throwable: Throwable) : State()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
index fdd3e66703..1068b92019 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
@@ -239,6 +239,14 @@ fun Event.isVideoMessage(): Boolean {
}
}
+fun Event.isAudioMessage(): Boolean {
+ return getClearType() == EventType.MESSAGE
+ && when (getClearContent()?.toModel()?.msgType) {
+ MessageType.MSGTYPE_AUDIO -> true
+ else -> false
+ }
+}
+
fun Event.isFileMessage(): Boolean {
return getClearType() == EventType.MESSAGE
&& when (getClearContent()?.toModel()?.msgType) {
@@ -246,6 +254,16 @@ fun Event.isFileMessage(): Boolean {
else -> false
}
}
+fun Event.isAttachmentMessage(): Boolean {
+ return getClearType() == EventType.MESSAGE
+ && when (getClearContent()?.toModel()?.msgType) {
+ MessageType.MSGTYPE_IMAGE,
+ MessageType.MSGTYPE_AUDIO,
+ MessageType.MSGTYPE_VIDEO,
+ MessageType.MSGTYPE_FILE -> true
+ else -> false
+ }
+}
fun Event.getRelationContent(): RelationDefaultContent? {
return if (isEncrypted()) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
index 449c670983..15066cc4a6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
@@ -83,4 +83,43 @@ interface ProfileService {
* @param refreshData set to true to fetch data from the homeserver
*/
fun getThreePidsLive(refreshData: Boolean): LiveData>
+
+ /**
+ * Get the pending 3Pids, i.e. ThreePids that have requested a token, but not yet validated by the user.
+ */
+ fun getPendingThreePids(): List
+
+ /**
+ * Get the pending 3Pids Live
+ */
+ fun getPendingThreePidsLive(): LiveData>
+
+ /**
+ * Add a 3Pids. This is the first step to add a ThreePid to an account. Then the threePid will be added to the pending threePid list.
+ */
+ fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback): Cancelable
+
+ /**
+ * Validate a code received by text message
+ */
+ fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback): Cancelable
+
+ /**
+ * Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid
+ */
+ fun finalizeAddingThreePid(threePid: ThreePid,
+ uiaSession: String?,
+ accountPassword: String?,
+ matrixCallback: MatrixCallback): Cancelable
+
+ /**
+ * Cancel adding a threepid. It will remove locally stored data about this ThreePid
+ */
+ fun cancelAddingThreePid(threePid: ThreePid,
+ matrixCallback: MatrixCallback): Cancelable
+
+ /**
+ * Remove a 3Pid from the Matrix account.
+ */
+ fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback): Cancelable
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
index e84b75d0af..b8e536cb33 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
@@ -110,13 +110,13 @@ interface SendService {
* Schedule this message to be resent
* @param localEcho the unsent local echo
*/
- fun resendTextMessage(localEcho: TimelineEvent): Cancelable?
+ fun resendTextMessage(localEcho: TimelineEvent): Cancelable
/**
* Schedule this message to be resent
* @param localEcho the unsent local echo
*/
- fun resendMediaMessage(localEcho: TimelineEvent): Cancelable?
+ fun resendMediaMessage(localEcho: TimelineEvent): Cancelable
/**
* Remove this failed message from the timeline
@@ -124,8 +124,16 @@ interface SendService {
*/
fun deleteFailedEcho(localEcho: TimelineEvent)
+ /**
+ * Delete all the events in one of the sending states
+ */
fun clearSendingQueue()
+ /**
+ * Cancel sending a specific event. It has to be in one of the sending states
+ */
+ fun cancelSend(eventId: String)
+
/**
* Resend all failed messages one by one (and keep order)
*/
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
index f0dd2f3025..be8849b20e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
@@ -37,7 +37,8 @@ enum class SendState {
internal companion object {
val HAS_FAILED_STATES = listOf(UNDELIVERED, FAILED_UNKNOWN_DEVICES)
val IS_SENT_STATES = listOf(SENT, SYNCED)
- val IS_SENDING_STATES = listOf(UNSENT, ENCRYPTING, SENDING)
+ val IS_PROGRESSING_STATES = listOf(ENCRYPTING, SENDING)
+ val IS_SENDING_STATES = IS_PROGRESSING_STATES + UNSENT
val PENDING_STATES = IS_SENDING_STATES + HAS_FAILED_STATES
}
@@ -45,5 +46,7 @@ enum class SendState {
fun hasFailed() = HAS_FAILED_STATES.contains(this)
+ fun isInProgress() = IS_PROGRESSING_STATES.contains(this)
+
fun isSending() = IS_SENDING_STATES.contains(this)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
index 79b71b208e..676f40a918 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
@@ -17,6 +17,9 @@
package org.matrix.android.sdk.internal.auth.registration
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
@@ -33,9 +36,6 @@ import org.matrix.android.sdk.internal.auth.db.PendingSessionData
import org.matrix.android.sdk.internal.network.RetrofitFactory
import org.matrix.android.sdk.internal.task.launchToCallback
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.delay
-import okhttp3.OkHttpClient
/**
* This class execute the registration request and is responsible to keep the session of interactive authentication
@@ -193,7 +193,7 @@ internal class DefaultRegistrationWizard(
val registrationParams = pendingSessionData.currentThreePidData?.registrationParams
?: throw IllegalStateException("developer error, no pending three pid")
val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first")
- val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url the send the code")
+ val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code")
val validationBody = ValidationCodeBody(
clientSecret = pendingSessionData.clientSecret,
sid = safeCurrentData.addThreePidRegistrationResponse.sid,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
index 9e1ef19b3a..11d5b4796a 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
@@ -20,9 +20,14 @@ package org.matrix.android.sdk.internal.crypto.attachments
import android.util.Base64
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
+import org.matrix.android.sdk.internal.util.base64ToBase64Url
+import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64
+import org.matrix.android.sdk.internal.util.base64UrlToBase64
import timber.log.Timber
import java.io.ByteArrayOutputStream
+import java.io.File
import java.io.InputStream
+import java.io.OutputStream
import java.security.MessageDigest
import java.security.SecureRandom
import javax.crypto.Cipher
@@ -35,8 +40,121 @@ internal object MXEncryptedAttachments {
private const val SECRET_KEY_SPEC_ALGORITHM = "AES"
private const val MESSAGE_DIGEST_ALGORITHM = "SHA-256"
+ fun encrypt(clearStream: InputStream, mimetype: String?, outputFile: File, progress: ((current: Int, total: Int) -> Unit)): EncryptedFileInfo {
+ val t0 = System.currentTimeMillis()
+ val secureRandom = SecureRandom()
+ val initVectorBytes = ByteArray(16) { 0.toByte() }
+
+ val ivRandomPart = ByteArray(8)
+ secureRandom.nextBytes(ivRandomPart)
+
+ System.arraycopy(ivRandomPart, 0, initVectorBytes, 0, ivRandomPart.size)
+
+ val key = ByteArray(32)
+ secureRandom.nextBytes(key)
+
+ val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+
+ outputFile.outputStream().use { outputStream ->
+ val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+ val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+ val ivParameterSpec = IvParameterSpec(initVectorBytes)
+ encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
+
+ val data = ByteArray(CRYPTO_BUFFER_SIZE)
+ var read: Int
+ var encodedBytes: ByteArray
+ clearStream.use { inputStream ->
+ val estimatedSize = inputStream.available()
+ progress.invoke(0, estimatedSize)
+ read = inputStream.read(data)
+ var totalRead = read
+ while (read != -1) {
+ progress.invoke(totalRead, estimatedSize)
+ encodedBytes = encryptCipher.update(data, 0, read)
+ messageDigest.update(encodedBytes, 0, encodedBytes.size)
+ outputStream.write(encodedBytes)
+ read = inputStream.read(data)
+ totalRead += read
+ }
+ }
+
+ // encrypt the latest chunk
+ encodedBytes = encryptCipher.doFinal()
+ messageDigest.update(encodedBytes, 0, encodedBytes.size)
+ outputStream.write(encodedBytes)
+ }
+
+ return EncryptedFileInfo(
+ url = null,
+ mimetype = mimetype,
+ key = EncryptedFileKey(
+ alg = "A256CTR",
+ ext = true,
+ keyOps = listOf("encrypt", "decrypt"),
+ kty = "oct",
+ k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+ ),
+ iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+ hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+ v = "v2"
+ )
+ .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
+ }
+
+// fun cipherInputStream(attachmentStream: InputStream, mimetype: String?): Pair {
+// val secureRandom = SecureRandom()
+//
+// // generate a random iv key
+// // Half of the IV is random, the lower order bits are zeroed
+// // such that the counter never wraps.
+// // See https://github.com/matrix-org/matrix-ios-kit/blob/3dc0d8e46b4deb6669ed44f72ad79be56471354c/MatrixKit/Models/Room/MXEncryptedAttachments.m#L75
+// val initVectorBytes = ByteArray(16) { 0.toByte() }
+//
+// val ivRandomPart = ByteArray(8)
+// secureRandom.nextBytes(ivRandomPart)
+//
+// System.arraycopy(ivRandomPart, 0, initVectorBytes, 0, ivRandomPart.size)
+//
+// val key = ByteArray(32)
+// secureRandom.nextBytes(key)
+//
+// val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+// val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+// val ivParameterSpec = IvParameterSpec(initVectorBytes)
+// encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
+//
+// val cipherInputStream = CipherInputStream(attachmentStream, encryptCipher)
+//
+// // Could it be possible to get the digest on the fly instead of
+// val info = EncryptedFileInfo(
+// url = null,
+// mimetype = mimetype,
+// key = EncryptedFileKey(
+// alg = "A256CTR",
+// ext = true,
+// key_ops = listOf("encrypt", "decrypt"),
+// kty = "oct",
+// k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+// ),
+// iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+// //hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+// v = "v2"
+// )
+//
+// val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+// return DigestInputStream(cipherInputStream, messageDigest) to info
+// }
+//
+// fun updateInfoWithDigest(digestInputStream: DigestInputStream, info: EncryptedFileInfo): EncryptedFileInfo {
+// return info.copy(
+// hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(digestInputStream.messageDigest.digest(), Base64.DEFAULT)))
+// )
+// }
+
/***
* Encrypt an attachment stream.
+ * DO NOT USE for big files, it will load all in memory
* @param attachmentStream the attachment stream. Will be closed after this method call.
* @param mimetype the mime type
* @return the encryption file info
@@ -59,14 +177,14 @@ internal object MXEncryptedAttachments {
val key = ByteArray(32)
secureRandom.nextBytes(key)
- ByteArrayOutputStream().use { outputStream ->
+ val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+ val byteArrayOutputStream = ByteArrayOutputStream()
+ byteArrayOutputStream.use { outputStream ->
val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
val ivParameterSpec = IvParameterSpec(initVectorBytes)
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
- val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
-
val data = ByteArray(CRYPTO_BUFFER_SIZE)
var read: Int
var encodedBytes: ByteArray
@@ -85,44 +203,26 @@ internal object MXEncryptedAttachments {
encodedBytes = encryptCipher.doFinal()
messageDigest.update(encodedBytes, 0, encodedBytes.size)
outputStream.write(encodedBytes)
-
- return EncryptionResult(
- encryptedFileInfo = EncryptedFileInfo(
- url = null,
- mimetype = mimetype,
- key = EncryptedFileKey(
- alg = "A256CTR",
- ext = true,
- keyOps = listOf("encrypt", "decrypt"),
- kty = "oct",
- k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
- ),
- iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
- hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
- v = "v2"
- ),
- encryptedByteArray = outputStream.toByteArray()
- )
- .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
- }
- }
-
- /**
- * Decrypt an attachment
- *
- * @param attachmentStream the attachment stream. Will be closed after this method call.
- * @param encryptedFileInfo the encryption file info
- * @return the decrypted attachment stream
- */
- fun decryptAttachment(attachmentStream: InputStream?, encryptedFileInfo: EncryptedFileInfo?): InputStream? {
- if (encryptedFileInfo?.isValid() != true) {
- Timber.e("## decryptAttachment() : some fields are not defined, or invalid key fields")
- return null
}
- val elementToDecrypt = encryptedFileInfo.toElementToDecrypt()
-
- return decryptAttachment(attachmentStream, elementToDecrypt)
+ return EncryptionResult(
+ encryptedFileInfo = EncryptedFileInfo(
+ url = null,
+ mimetype = mimetype,
+ key = EncryptedFileKey(
+ alg = "A256CTR",
+ ext = true,
+ keyOps = listOf("encrypt", "decrypt"),
+ kty = "oct",
+ k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+ ),
+ iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+ hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+ v = "v2"
+ ),
+ encryptedByteArray = byteArrayOutputStream.toByteArray()
+ )
+ .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
}
/**
@@ -130,84 +230,61 @@ internal object MXEncryptedAttachments {
*
* @param attachmentStream the attachment stream. Will be closed after this method call.
* @param elementToDecrypt the elementToDecrypt info
- * @return the decrypted attachment stream
+ * @param outputStream the outputStream where the decrypted attachment will be write.
+ * @return true in case of success, false in case of error
*/
- fun decryptAttachment(attachmentStream: InputStream?, elementToDecrypt: ElementToDecrypt?): InputStream? {
+ fun decryptAttachment(attachmentStream: InputStream?, elementToDecrypt: ElementToDecrypt?, outputStream: OutputStream): Boolean {
// sanity checks
if (null == attachmentStream || elementToDecrypt == null) {
Timber.e("## decryptAttachment() : null stream")
- return null
+ return false
}
val t0 = System.currentTimeMillis()
- ByteArrayOutputStream().use { outputStream ->
- try {
- val key = Base64.decode(base64UrlToBase64(elementToDecrypt.k), Base64.DEFAULT)
- val initVectorBytes = Base64.decode(elementToDecrypt.iv, Base64.DEFAULT)
+ try {
+ val key = Base64.decode(base64UrlToBase64(elementToDecrypt.k), Base64.DEFAULT)
+ val initVectorBytes = Base64.decode(elementToDecrypt.iv, Base64.DEFAULT)
- val decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
- val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
- val ivParameterSpec = IvParameterSpec(initVectorBytes)
- decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
+ val decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+ val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+ val ivParameterSpec = IvParameterSpec(initVectorBytes)
+ decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
- val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+ val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
- var read: Int
- val data = ByteArray(CRYPTO_BUFFER_SIZE)
- var decodedBytes: ByteArray
+ var read: Int
+ val data = ByteArray(CRYPTO_BUFFER_SIZE)
+ var decodedBytes: ByteArray
- attachmentStream.use { inputStream ->
+ attachmentStream.use { inputStream ->
+ read = inputStream.read(data)
+ while (read != -1) {
+ messageDigest.update(data, 0, read)
+ decodedBytes = decryptCipher.update(data, 0, read)
+ outputStream.write(decodedBytes)
read = inputStream.read(data)
- while (read != -1) {
- messageDigest.update(data, 0, read)
- decodedBytes = decryptCipher.update(data, 0, read)
- outputStream.write(decodedBytes)
- read = inputStream.read(data)
- }
}
-
- // decrypt the last chunk
- decodedBytes = decryptCipher.doFinal()
- outputStream.write(decodedBytes)
-
- val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))
-
- if (elementToDecrypt.sha256 != currentDigestValue) {
- Timber.e("## decryptAttachment() : Digest value mismatch")
- return null
- }
-
- return outputStream.toByteArray().inputStream()
- .also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") }
- } catch (oom: OutOfMemoryError) {
- Timber.e(oom, "## decryptAttachment() failed: OOM")
- } catch (e: Exception) {
- Timber.e(e, "## decryptAttachment() failed")
}
+
+ // decrypt the last chunk
+ decodedBytes = decryptCipher.doFinal()
+ outputStream.write(decodedBytes)
+
+ val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))
+
+ if (elementToDecrypt.sha256 != currentDigestValue) {
+ Timber.e("## decryptAttachment() : Digest value mismatch")
+ return false
+ }
+
+ return true.also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") }
+ } catch (oom: OutOfMemoryError) {
+ Timber.e(oom, "## decryptAttachment() failed: OOM")
+ } catch (e: Exception) {
+ Timber.e(e, "## decryptAttachment() failed")
}
- return null
- }
-
- /**
- * Base64 URL conversion methods
- */
-
- private fun base64UrlToBase64(base64Url: String): String {
- return base64Url.replace('-', '+')
- .replace('_', '/')
- }
-
- internal fun base64ToBase64Url(base64: String): String {
- return base64.replace("\n".toRegex(), "")
- .replace("\\+".toRegex(), "-")
- .replace('/', '_')
- .replace("=", "")
- }
-
- private fun base64ToUnpaddedBase64(base64: String): String {
- return base64.replace("\n".toRegex(), "")
- .replace("=", "")
+ return false
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt
new file mode 100644
index 0000000000..7ca5158f64
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.crypto.attachments
+
+import android.util.Base64
+import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64
+import java.io.FilterInputStream
+import java.io.IOException
+import java.io.InputStream
+import java.security.MessageDigest
+
+class MatrixDigestCheckInputStream(
+ inputStream: InputStream?,
+ private val expectedDigest: String
+) : FilterInputStream(inputStream) {
+
+ private val digest = MessageDigest.getInstance("SHA-256")
+
+ @Throws(IOException::class)
+ override fun read(): Int {
+ val b = `in`.read()
+ if (b >= 0) {
+ digest.update(b.toByte())
+ }
+
+ if (b == -1) {
+ ensureDigest()
+ }
+ return b
+ }
+
+ @Throws(IOException::class)
+ override fun read(
+ b: ByteArray,
+ off: Int,
+ len: Int): Int {
+ val n = `in`.read(b, off, len)
+ if (n > 0) {
+ digest.update(b, off, n)
+ }
+
+ if (n == -1) {
+ ensureDigest()
+ }
+ return n
+ }
+
+ @Throws(IOException::class)
+ private fun ensureDigest() {
+ val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(digest.digest(), Base64.DEFAULT))
+ if (currentDigestValue != expectedDigest) {
+ throw IOException("Bad digest")
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
index 5a55ec2a9c..ae5852452a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
@@ -55,14 +55,14 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_verification_robot)
32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_verification_hat)
33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_verification_glasses)
- 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench, R.drawable.ic_verification_wrench)
+ 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_spanner, R.drawable.ic_verification_spanner)
35 -> EmojiRepresentation("🎅", R.string.verification_emoji_santa, R.drawable.ic_verification_santa)
- 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup, R.drawable.ic_verification_thumbs_up)
+ 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbs_up, R.drawable.ic_verification_thumbs_up)
37 -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella, R.drawable.ic_verification_umbrella)
38 -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass, R.drawable.ic_verification_hourglass)
39 -> EmojiRepresentation("⏰", R.string.verification_emoji_clock, R.drawable.ic_verification_clock)
40 -> EmojiRepresentation("🎁", R.string.verification_emoji_gift, R.drawable.ic_verification_gift)
- 41 -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb, R.drawable.ic_verification_light_bulb)
+ 41 -> EmojiRepresentation("💡", R.string.verification_emoji_light_bulb, R.drawable.ic_verification_light_bulb)
42 -> EmojiRepresentation("📕", R.string.verification_emoji_book, R.drawable.ic_verification_book)
43 -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil, R.drawable.ic_verification_pencil)
44 -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip, R.drawable.ic_verification_paperclip)
@@ -74,7 +74,7 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
50 -> EmojiRepresentation("🏁", R.string.verification_emoji_flag, R.drawable.ic_verification_flag)
51 -> EmojiRepresentation("🚂", R.string.verification_emoji_train, R.drawable.ic_verification_train)
52 -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle, R.drawable.ic_verification_bicycle)
- 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane, R.drawable.ic_verification_airplane)
+ 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_aeroplane, R.drawable.ic_verification_aeroplane)
54 -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket, R.drawable.ic_verification_rocket)
55 -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy, R.drawable.ic_verification_trophy)
56 -> EmojiRepresentation("⚽", R.string.verification_emoji_ball, R.drawable.ic_verification_ball)
@@ -82,7 +82,7 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
58 -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet, R.drawable.ic_verification_trumpet)
59 -> EmojiRepresentation("🔔", R.string.verification_emoji_bell, R.drawable.ic_verification_bell)
60 -> EmojiRepresentation("⚓", R.string.verification_emoji_anchor, R.drawable.ic_verification_anchor)
- 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone, R.drawable.ic_verification_headphone)
+ 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphones, R.drawable.ic_verification_headphones)
62 -> EmojiRepresentation("📁", R.string.verification_emoji_folder, R.drawable.ic_verification_folder)
/* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin, R.drawable.ic_verification_pin)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
index 7d2a4ea581..ad05406aa0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
@@ -20,18 +20,24 @@ package org.matrix.android.sdk.internal.database
import io.realm.DynamicRealm
import io.realm.RealmMigration
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
import timber.log.Timber
import javax.inject.Inject
class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
+ companion object {
+ const val SESSION_STORE_SCHEMA_VERSION = 4L
+ }
+
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
if (oldVersion <= 0) migrateTo1(realm)
if (oldVersion <= 1) migrateTo2(realm)
if (oldVersion <= 2) migrateTo3(realm)
+ if (oldVersion <= 3) migrateTo4(realm)
}
private fun migrateTo1(realm: DynamicRealm) {
@@ -63,4 +69,17 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
}
}
+
+ private fun migrateTo4(realm: DynamicRealm) {
+ Timber.d("Step 3 -> 4")
+ realm.schema.create("PendingThreePidEntity")
+ .addField(PendingThreePidEntityFields.CLIENT_SECRET, String::class.java)
+ .setRequired(PendingThreePidEntityFields.CLIENT_SECRET, true)
+ .addField(PendingThreePidEntityFields.EMAIL, String::class.java)
+ .addField(PendingThreePidEntityFields.MSISDN, String::class.java)
+ .addField(PendingThreePidEntityFields.SEND_ATTEMPT, Int::class.java)
+ .addField(PendingThreePidEntityFields.SID, String::class.java)
+ .setRequired(PendingThreePidEntityFields.SID, true)
+ .addField(PendingThreePidEntityFields.SUBMIT_URL, String::class.java)
+ }
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
index 456eecc54a..d5c259050f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
@@ -19,13 +19,14 @@ package org.matrix.android.sdk.internal.database
import android.content.Context
import androidx.core.content.edit
+import io.realm.Realm
+import io.realm.RealmConfiguration
+import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.internal.database.model.SessionRealmModule
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.UserMd5
import org.matrix.android.sdk.internal.session.SessionModule
-import io.realm.Realm
-import io.realm.RealmConfiguration
import timber.log.Timber
import java.io.File
import javax.inject.Inject
@@ -46,20 +47,16 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
val migration: RealmSessionStoreMigration,
context: Context) {
- companion object {
- const val SESSION_STORE_SCHEMA_VERSION = 3L
- }
-
// Keep legacy preferences name for compatibility reason
private val sharedPreferences = context.getSharedPreferences("im.vector.matrix.android.realm", Context.MODE_PRIVATE)
fun create(): RealmConfiguration {
val shouldClearRealm = sharedPreferences.getBoolean("$REALM_SHOULD_CLEAR_FLAG_$sessionId", false)
if (shouldClearRealm) {
- Timber.v("************************************************************")
- Timber.v("The realm file session was corrupted and couldn't be loaded.")
- Timber.v("The file has been deleted to recover.")
- Timber.v("************************************************************")
+ Timber.e("************************************************************")
+ Timber.e("The realm file session was corrupted and couldn't be loaded.")
+ Timber.e("The file has been deleted to recover.")
+ Timber.e("************************************************************")
deleteRealmFiles()
}
sharedPreferences.edit {
@@ -74,7 +71,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
}
.modules(SessionRealmModule())
- .schemaVersion(SESSION_STORE_SCHEMA_VERSION)
+ .schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
.migration(migration)
.build()
@@ -90,6 +87,11 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
// Delete all the realm files of the session
private fun deleteRealmFiles() {
+ if (BuildConfig.DEBUG) {
+ Timber.e("No op because it is a debug build")
+ return
+ }
+
listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file ->
try {
File(directory, file).deleteRecursively()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt
new file mode 100644
index 0000000000..2f5643d7bc
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.database.model
+
+import io.realm.RealmObject
+
+/**
+ * This class is used to store pending threePid data, when user wants to add a threePid to his account
+ */
+internal open class PendingThreePidEntity(
+ var email: String? = null,
+ var msisdn: String? = null,
+ var clientSecret: String = "",
+ var sendAttempt: Int = 0,
+ var sid: String = "",
+ var submitUrl: String? = null
+) : RealmObject()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
index ea466db352..2c45cfcdbf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
@@ -36,6 +36,7 @@ import io.realm.annotations.RealmModule
RoomSummaryEntity::class,
RoomTagEntity::class,
SyncEntity::class,
+ PendingThreePidEntity::class,
UserEntity::class,
IgnoredUserEntity::class,
BreadcrumbsEntity::class,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
index 7ce260e54e..98dec301ee 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
@@ -24,6 +24,7 @@ import okio.BufferedSink
import okio.ForwardingSink
import okio.Sink
import okio.buffer
+import org.matrix.android.sdk.api.extensions.tryThis
import java.io.IOException
internal class ProgressRequestBody(private val delegate: RequestBody,
@@ -35,15 +36,13 @@ internal class ProgressRequestBody(private val delegate: RequestBody,
return delegate.contentType()
}
- override fun contentLength(): Long {
- try {
- return delegate.contentLength()
- } catch (e: IOException) {
- e.printStackTrace()
- }
+ override fun isOneShot() = delegate.isOneShot()
- return -1
- }
+ override fun isDuplex() = delegate.isDuplex()
+
+ val length = tryThis { delegate.contentLength() } ?: -1
+
+ override fun contentLength() = length
@Throws(IOException::class)
override fun writeTo(sink: BufferedSink) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
index 97ebe943ec..aa4114c8c2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
@@ -143,20 +143,22 @@ internal class DefaultFileService @Inject constructor(
Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${!source.exhausted()}")
if (elementToDecrypt != null) {
- Timber.v("## decrypt file")
- val decryptedStream = MXEncryptedAttachments.decryptAttachment(source.inputStream(), elementToDecrypt)
+ Timber.v("## FileService: decrypt file")
+ val decryptSuccess = MXEncryptedAttachments.decryptAttachment(
+ source.inputStream(),
+ elementToDecrypt,
+ destFile.outputStream().buffered()
+ )
response.close()
- if (decryptedStream == null) {
+ if (!decryptSuccess) {
return@flatMap Try.Failure(IllegalStateException("Decryption error"))
- } else {
- decryptedStream.use {
- writeToFile(decryptedStream, destFile)
- }
}
} else {
writeToFile(source.inputStream(), destFile)
response.close()
}
+ } else {
+ Timber.v("## FileService: cache hit for $url")
}
Try.just(copyFile(destFile, downloadMode))
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
index aa8b98ae62..951c24ccb7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
@@ -74,8 +74,8 @@ internal class DefaultContentUploadStateTracker @Inject constructor() : ContentU
updateState(key, progressData)
}
- internal fun setEncrypting(key: String) {
- val progressData = ContentUploadStateTracker.State.Encrypting
+ internal fun setEncrypting(key: String, current: Long, total: Long) {
+ val progressData = ContentUploadStateTracker.State.Encrypting(current, total)
updateState(key, progressData)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
index 5e5380fce1..4ddf394b00 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
@@ -23,13 +23,16 @@ import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
+import okio.BufferedSink
+import okio.source
import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.extensions.tryThis
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.internal.di.Authenticated
import org.matrix.android.sdk.internal.network.ProgressRequestBody
@@ -38,6 +41,7 @@ import org.matrix.android.sdk.internal.network.toFailure
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
+import java.util.UUID
import javax.inject.Inject
internal class FileUploader @Inject constructor(@Authenticated
@@ -54,7 +58,21 @@ internal class FileUploader @Inject constructor(@Authenticated
filename: String?,
mimeType: String?,
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
- val uploadBody = file.asRequestBody(mimeType?.toMediaTypeOrNull())
+ val uploadBody = object : RequestBody() {
+ override fun contentLength() = file.length()
+
+ // Disable okhttp auto resend for 'large files'
+ override fun isOneShot() = contentLength() == 0L || contentLength() >= 1_000_000
+
+ override fun contentType(): MediaType? {
+ return mimeType?.toMediaTypeOrNull()
+ }
+
+ override fun writeTo(sink: BufferedSink) {
+ file.source().use { sink.writeAll(it) }
+ }
+ }
+
return upload(uploadBody, filename, progressListener)
}
@@ -70,14 +88,18 @@ internal class FileUploader @Inject constructor(@Authenticated
filename: String?,
mimeType: String?,
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
- return withContext(Dispatchers.IO) {
- val inputStream = context.contentResolver.openInputStream(uri) ?: throw FileNotFoundException()
-
- inputStream.use {
- uploadByteArray(it.readBytes(), filename, mimeType, progressListener)
- }
+ val inputStream = withContext(Dispatchers.IO) {
+ context.contentResolver.openInputStream(uri)
+ } ?: throw FileNotFoundException()
+ val workingFile = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+ workingFile.outputStream().use {
+ inputStream.copyTo(it)
+ }
+ return uploadFile(workingFile, filename, mimeType, progressListener).also {
+ tryThis { workingFile.delete() }
}
}
+
private suspend fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): ContentUploadResponse {
val urlBuilder = uploadUrl.toHttpUrlOrNull()?.newBuilder() ?: throw RuntimeException()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt
new file mode 100644
index 0000000000..a125c0aea4
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.content
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Matrix
+import androidx.exifinterface.media.ExifInterface
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import timber.log.Timber
+import java.io.File
+import java.util.UUID
+import javax.inject.Inject
+
+internal class ImageCompressor @Inject constructor() {
+ suspend fun compress(
+ context: Context,
+ imageFile: File,
+ desiredWidth: Int,
+ desiredHeight: Int,
+ desiredQuality: Int = 80): File {
+ return withContext(Dispatchers.IO) {
+ val compressedBitmap = BitmapFactory.Options().run {
+ inJustDecodeBounds = true
+ decodeBitmap(imageFile, this)
+ inSampleSize = calculateInSampleSize(outWidth, outHeight, desiredWidth, desiredHeight)
+ inJustDecodeBounds = false
+ decodeBitmap(imageFile, this)?.let {
+ rotateBitmap(imageFile, it)
+ }
+ } ?: return@withContext imageFile
+
+ val destinationFile = createDestinationFile(context)
+
+ runCatching {
+ destinationFile.outputStream().use {
+ compressedBitmap.compress(Bitmap.CompressFormat.JPEG, desiredQuality, it)
+ }
+ }
+
+ return@withContext destinationFile
+ }
+ }
+
+ private fun rotateBitmap(file: File, bitmap: Bitmap): Bitmap {
+ file.inputStream().use { inputStream ->
+ try {
+ ExifInterface(inputStream).let { exifInfo ->
+ val orientation = exifInfo.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
+ val matrix = Matrix()
+ when (orientation) {
+ ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f)
+ ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f)
+ ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f)
+ ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.preScale(-1f, 1f)
+ ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.preScale(1f, -1f)
+ ExifInterface.ORIENTATION_TRANSPOSE -> {
+ matrix.preRotate(-90f)
+ matrix.preScale(-1f, 1f)
+ }
+ ExifInterface.ORIENTATION_TRANSVERSE -> {
+ matrix.preRotate(90f)
+ matrix.preScale(-1f, 1f)
+ }
+ else -> return bitmap
+ }
+ return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
+ }
+ } catch (e: Exception) {
+ Timber.e(e, "Cannot read orientation")
+ }
+ }
+ return bitmap
+ }
+
+ // https://developer.android.com/topic/performance/graphics/load-bitmap
+ private fun calculateInSampleSize(width: Int, height: Int, desiredWidth: Int, desiredHeight: Int): Int {
+ var inSampleSize = 1
+
+ if (width > desiredWidth || height > desiredHeight) {
+ val halfHeight: Int = height / 2
+ val halfWidth: Int = width / 2
+
+ // Calculate the largest inSampleSize value that is a power of 2 and keeps both
+ // height and width larger than the requested height and width.
+ while (halfHeight / inSampleSize >= desiredHeight && halfWidth / inSampleSize >= desiredWidth) {
+ inSampleSize *= 2
+ }
+ }
+
+ return inSampleSize
+ }
+
+ private fun decodeBitmap(file: File, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? {
+ return try {
+ file.inputStream().use { inputStream ->
+ BitmapFactory.decodeStream(inputStream, null, options)
+ }
+ } catch (e: Exception) {
+ Timber.e(e, "Cannot decode Bitmap")
+ null
+ }
+ }
+
+ private fun createDestinationFile(context: Context): File {
+ return File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
index 720269404f..6e70906d13 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
@@ -22,8 +22,7 @@ import android.graphics.BitmapFactory
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
-import id.zelory.compressor.Compressor
-import id.zelory.compressor.constraint.default
+import org.matrix.android.sdk.api.extensions.tryThis
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toContent
@@ -37,6 +36,7 @@ import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
import org.matrix.android.sdk.internal.network.ProgressRequestBody
import org.matrix.android.sdk.internal.session.DefaultFileService
+import org.matrix.android.sdk.internal.session.room.send.CancelSendTracker
import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker
import org.matrix.android.sdk.internal.worker.SessionWorkerParams
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
@@ -71,6 +71,8 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
@Inject lateinit var fileUploader: FileUploader
@Inject lateinit var contentUploadStateTracker: DefaultContentUploadStateTracker
@Inject lateinit var fileService: DefaultFileService
+ @Inject lateinit var cancelSendTracker: CancelSendTracker
+ @Inject lateinit var imageCompressor: ImageCompressor
override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData(inputData)
@@ -98,9 +100,15 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
sessionComponent.inject(this)
- val attachment = params.attachment
+ val allCancelled = params.events.all { cancelSendTracker.isCancelRequestedFor(it.eventId, it.roomId) }
+ if (allCancelled) {
+ // there is no point in uploading the image!
+ return Result.success(inputData)
+ .also { Timber.e("## Send: Work cancelled by user") }
+ }
- var newImageAttributes: NewImageAttributes? = null
+ val attachment = params.attachment
+ val filesToDelete = mutableListOf()
try {
val inputStream = context.contentResolver.openInputStream(attachment.queryUri)
@@ -112,124 +120,100 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
)
)
- inputStream.use {
- var uploadedThumbnailUrl: String? = null
- var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null
-
- ThumbnailExtractor.extractThumbnail(context, params.attachment)?.let { thumbnailData ->
- val thumbnailProgressListener = object : ProgressRequestBody.Listener {
- override fun onProgress(current: Long, total: Long) {
- notifyTracker(params) { contentUploadStateTracker.setProgressThumbnail(it, current, total) }
- }
- }
-
- try {
- val contentUploadResponse = if (params.isEncrypted) {
- Timber.v("Encrypt thumbnail")
- notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) }
- val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream(), thumbnailData.mimeType)
- uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
- fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
- "thumb_${attachment.name}",
- "application/octet-stream",
- thumbnailProgressListener)
- } else {
- fileUploader.uploadByteArray(thumbnailData.bytes,
- "thumb_${attachment.name}",
- thumbnailData.mimeType,
- thumbnailProgressListener)
- }
-
- uploadedThumbnailUrl = contentUploadResponse.contentUri
- } catch (t: Throwable) {
- Timber.e(t, "Thumbnail update failed")
- }
- }
-
- val progressListener = object : ProgressRequestBody.Listener {
- override fun onProgress(current: Long, total: Long) {
- notifyTracker(params) {
- if (isStopped) {
- contentUploadStateTracker.setFailure(it, Throwable("Cancelled"))
- } else {
- contentUploadStateTracker.setProgress(it, current, total)
- }
- }
- }
- }
-
- var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
-
- return try {
- // Compressor library works with File instead of Uri for now. Since Scoped Storage doesn't allow us to access files directly, we should
- // copy it to a cache folder by using InputStream and OutputStream.
- // https://github.com/zetbaitsu/Compressor/pull/150
- // As soon as the above PR is merged, we can use attachment.queryUri instead of creating a cacheFile.
- var cacheFile = File.createTempFile(attachment.name ?: UUID.randomUUID().toString(), ".jpg", context.cacheDir)
- cacheFile.parentFile?.mkdirs()
- if (cacheFile.exists()) {
- cacheFile.delete()
- }
- cacheFile.createNewFile()
- cacheFile.deleteOnExit()
-
- val outputStream = cacheFile.outputStream()
- outputStream.use {
- inputStream.copyTo(outputStream)
- }
-
- if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) {
- cacheFile = Compressor.compress(context, cacheFile) {
- default(
- width = MAX_IMAGE_SIZE,
- height = MAX_IMAGE_SIZE
- )
- }.also { compressedFile ->
- val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
- BitmapFactory.decodeFile(compressedFile.absolutePath, options)
- val fileSize = compressedFile.length().toInt()
- newImageAttributes = NewImageAttributes(
- options.outWidth,
- options.outHeight,
- fileSize
- )
- }
- }
-
- val contentUploadResponse = if (params.isEncrypted) {
- Timber.v("Encrypt file")
- notifyTracker(params) { contentUploadStateTracker.setEncrypting(it) }
-
- val encryptionResult = MXEncryptedAttachments.encryptAttachment(cacheFile.inputStream(), attachment.getSafeMimeType())
- uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
-
- fileUploader
- .uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
- } else {
- fileUploader
- .uploadFile(cacheFile, attachment.name, attachment.getSafeMimeType(), progressListener)
- }
-
- // If it's a file update the file service so that it does not redownload?
- if (params.attachment.type == ContentAttachmentData.Type.FILE) {
- context.contentResolver.openInputStream(attachment.queryUri)?.let {
- fileService.storeDataFor(contentUploadResponse.contentUri, params.attachment.getSafeMimeType(), it)
- }
- }
-
- handleSuccess(params,
- contentUploadResponse.contentUri,
- uploadedFileEncryptedFileInfo,
- uploadedThumbnailUrl,
- uploadedThumbnailEncryptedFileInfo,
- newImageAttributes)
- } catch (t: Throwable) {
- Timber.e(t)
- handleFailure(params, t)
+ // always use a temporary file, it guaranties that we could report progress on upload and simplifies the flows
+ val workingFile = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+ .also { filesToDelete.add(it) }
+ workingFile.outputStream().use { outputStream ->
+ inputStream.use { inputStream ->
+ inputStream.copyTo(outputStream)
}
}
+
+ val uploadThumbnailResult = dealWithThumbnail(params)
+
+ val progressListener = object : ProgressRequestBody.Listener {
+ override fun onProgress(current: Long, total: Long) {
+ notifyTracker(params) {
+ if (isStopped) {
+ contentUploadStateTracker.setFailure(it, Throwable("Cancelled"))
+ } else {
+ contentUploadStateTracker.setProgress(it, current, total)
+ }
+ }
+ }
+ }
+
+ var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
+
+ return try {
+ val fileToUpload: File
+ var newImageAttributes: NewImageAttributes? = null
+
+ if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) {
+ fileToUpload = imageCompressor.compress(context, workingFile, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE)
+ .also { compressedFile ->
+ // Get new Bitmap size
+ compressedFile.inputStream().use {
+ val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
+ val bitmap = BitmapFactory.decodeStream(it, null, options)
+ val fileSize = bitmap?.byteCount ?: 0
+ newImageAttributes = NewImageAttributes(
+ options.outWidth,
+ options.outHeight,
+ fileSize
+ )
+ }
+ }
+ .also { filesToDelete.add(it) }
+ } else {
+ fileToUpload = workingFile
+ }
+
+ val contentUploadResponse = if (params.isEncrypted) {
+ Timber.v("## FileService: Encrypt file")
+
+ val tmpEncrypted = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+ .also { filesToDelete.add(it) }
+
+ uploadedFileEncryptedFileInfo =
+ MXEncryptedAttachments.encrypt(fileToUpload.inputStream(), attachment.getSafeMimeType(), tmpEncrypted) { read, total ->
+ notifyTracker(params) {
+ contentUploadStateTracker.setEncrypting(it, read.toLong(), total.toLong())
+ }
+ }
+
+ Timber.v("## FileService: Uploading file")
+
+ fileUploader
+ .uploadFile(tmpEncrypted, attachment.name, "application/octet-stream", progressListener)
+ } else {
+ Timber.v("## FileService: Clear file")
+ fileUploader
+ .uploadFile(fileToUpload, attachment.name, attachment.getSafeMimeType(), progressListener)
+ }
+
+ Timber.v("## FileService: Update cache storage for ${contentUploadResponse.contentUri}")
+ try {
+ context.contentResolver.openInputStream(attachment.queryUri)?.let {
+ fileService.storeDataFor(contentUploadResponse.contentUri, params.attachment.getSafeMimeType(), it)
+ }
+ Timber.v("## FileService: cache storage updated")
+ } catch (failure: Throwable) {
+ Timber.e(failure, "## FileService: Failed to update file cache")
+ }
+
+ handleSuccess(params,
+ contentUploadResponse.contentUri,
+ uploadedFileEncryptedFileInfo,
+ uploadThumbnailResult?.uploadedThumbnailUrl,
+ uploadThumbnailResult?.uploadedThumbnailEncryptedFileInfo,
+ newImageAttributes)
+ } catch (t: Throwable) {
+ Timber.e(t, "## FileService: ERROR ${t.localizedMessage}")
+ handleFailure(params, t)
+ }
} catch (e: Exception) {
- Timber.e(e)
+ Timber.e(e, "## FileService: ERROR")
notifyTracker(params) { contentUploadStateTracker.setFailure(it, e) }
return Result.success(
WorkerParamsFactory.toData(
@@ -238,9 +222,61 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
)
)
)
+ } finally {
+ // Delete all temporary files
+ filesToDelete.forEach {
+ tryThis { it.delete() }
+ }
}
}
+ private data class UploadThumbnailResult(
+ val uploadedThumbnailUrl: String,
+ val uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo?
+ )
+
+ /**
+ * If appropriate, it will create and upload a thumbnail
+ */
+ private suspend fun dealWithThumbnail(params: Params): UploadThumbnailResult? {
+ return ThumbnailExtractor.extractThumbnail(context, params.attachment)
+ ?.let { thumbnailData ->
+ val thumbnailProgressListener = object : ProgressRequestBody.Listener {
+ override fun onProgress(current: Long, total: Long) {
+ notifyTracker(params) { contentUploadStateTracker.setProgressThumbnail(it, current, total) }
+ }
+ }
+
+ try {
+ if (params.isEncrypted) {
+ Timber.v("Encrypt thumbnail")
+ notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) }
+ val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream(), thumbnailData.mimeType)
+ val contentUploadResponse = fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
+ "thumb_${params.attachment.name}",
+ "application/octet-stream",
+ thumbnailProgressListener)
+ UploadThumbnailResult(
+ contentUploadResponse.contentUri,
+ encryptionResult.encryptedFileInfo
+ )
+ } else {
+ val contentUploadResponse = fileUploader.uploadByteArray(thumbnailData.bytes,
+ "thumb_${params.attachment.name}",
+ thumbnailData.mimeType,
+ thumbnailProgressListener)
+ UploadThumbnailResult(
+ contentUploadResponse.contentUri,
+ null
+ )
+ }
+ } catch (t: Throwable) {
+ Timber.e(t, "Thumbnail upload failed")
+ null
+ }
+ }
+ }
+
private fun handleFailure(params: Params, failure: Throwable): Result {
notifyTracker(params) { contentUploadStateTracker.setFailure(it, failure) }
@@ -259,7 +295,6 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
thumbnailUrl: String?,
thumbnailEncryptedFileInfo: EncryptedFileInfo?,
newImageAttributes: NewImageAttributes?): Result {
- Timber.v("handleSuccess $attachmentUrl, work is stopped $isStopped")
notifyTracker(params) { contentUploadStateTracker.setSuccess(it) }
val updatedEvents = params.events
@@ -268,7 +303,9 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
}
val sendParams = MultipleEventSendingDispatcherWorker.Params(params.sessionId, updatedEvents, params.isEncrypted)
- return Result.success(WorkerParamsFactory.toData(sendParams))
+ return Result.success(WorkerParamsFactory.toData(sendParams)).also {
+ Timber.v("## handleSuccess $attachmentUrl, work is stopped $isStopped")
+ }
}
private fun updateEvent(event: Event,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
index 295a829b08..c4ba95af84 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
@@ -61,19 +61,23 @@ internal class DefaultContentDownloadStateTracker @Inject constructor() : Progre
// private fun URL.toKey() = toString()
override fun update(url: String, bytesRead: Long, contentLength: Long, done: Boolean) {
- Timber.v("## DL Progress url:$url read:$bytesRead total:$contentLength done:$done")
- if (done) {
- updateState(url, ContentDownloadStateTracker.State.Success)
- } else {
- updateState(url, ContentDownloadStateTracker.State.Downloading(bytesRead, contentLength, contentLength == -1L))
+ mainHandler.post {
+ Timber.v("## DL Progress url:$url read:$bytesRead total:$contentLength done:$done")
+ if (done) {
+ updateState(url, ContentDownloadStateTracker.State.Success)
+ } else {
+ updateState(url, ContentDownloadStateTracker.State.Downloading(bytesRead, contentLength, contentLength == -1L))
+ }
}
}
override fun error(url: String, errorCode: Int) {
- Timber.v("## DL Progress Error code:$errorCode")
- updateState(url, ContentDownloadStateTracker.State.Failure(errorCode))
- listeners[url]?.forEach {
- tryThis { it.onDownloadStateUpdate(ContentDownloadStateTracker.State.Failure(errorCode)) }
+ mainHandler.post {
+ Timber.v("## DL Progress Error code:$errorCode")
+ updateState(url, ContentDownloadStateTracker.State.Failure(errorCode))
+ listeners[url]?.forEach {
+ tryThis { it.onDownloadStateUpdate(ContentDownloadStateTracker.State.Failure(errorCode)) }
+ }
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
index ac33c2666f..45d7d48a18 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
@@ -23,7 +23,6 @@ import org.matrix.android.sdk.api.session.identity.FoundThreePid
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.identity.toMedium
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments.base64ToBase64Url
import org.matrix.android.sdk.internal.crypto.tools.withOlmUtility
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.network.executeRequest
@@ -32,6 +31,7 @@ import org.matrix.android.sdk.internal.session.identity.model.IdentityHashDetail
import org.matrix.android.sdk.internal.session.identity.model.IdentityLookUpParams
import org.matrix.android.sdk.internal.session.identity.model.IdentityLookUpResponse
import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.base64ToBase64Url
import java.util.Locale
import javax.inject.Inject
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt
new file mode 100644
index 0000000000..ff81ad6a5c
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddEmailBody(
+ /**
+ * Required. A unique string generated by the client, and used to identify the validation attempt.
+ * It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed
+ * 255 characters and it must not be empty.
+ */
+ @Json(name = "client_secret")
+ val clientSecret: String,
+
+ /**
+ * Required. The email address to validate.
+ */
+ @Json(name = "email")
+ val email: String,
+
+ /**
+ * Required. The server will only send an email if the send_attempt is a number greater than the most
+ * recent one which it has seen, scoped to that email + client_secret pair. This is to avoid repeatedly
+ * sending the same email in the case of request retries between the POSTing user and the identity server.
+ * The client should increment this value if they desire a new email (e.g. a reminder) to be sent.
+ * If they do not, the server should respond with success but not resend the email.
+ */
+ @Json(name = "send_attempt")
+ val sendAttempt: Int
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt
new file mode 100644
index 0000000000..8654d7c5ba
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddEmailResponse(
+ /**
+ * Required. The session ID. Session IDs are opaque strings that must consist entirely
+ * of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
+ */
+ @Json(name = "sid")
+ val sid: String
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt
new file mode 100644
index 0000000000..64c53f6729
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddMsisdnBody(
+ /**
+ * Required. A unique string generated by the client, and used to identify the validation attempt.
+ * It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed
+ * 255 characters and it must not be empty.
+ */
+ @Json(name = "client_secret")
+ val clientSecret: String,
+
+ /**
+ * Required. The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in
+ * phone_number should be parsed as if it were dialled from.
+ */
+ @Json(name = "country")
+ val country: String,
+
+ /**
+ * Required. The phone number to validate.
+ */
+ @Json(name = "phone_number")
+ val phoneNumber: String,
+
+ /**
+ * Required. The server will only send an SMS if the send_attempt is a number greater than the most
+ * recent one which it has seen, scoped to that country + phone_number + client_secret triple. This
+ * is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user
+ * and the identity server. The client should increment this value if they desire a new SMS (e.g. a
+ * reminder) to be sent.
+ */
+ @Json(name = "send_attempt")
+ val sendAttempt: Int
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt
new file mode 100644
index 0000000000..b4c137b3a1
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddMsisdnResponse(
+ /**
+ * Required. The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-].
+ * Their length must not exceed 255 characters and they must not be empty.
+ */
+ @Json(name = "sid")
+ val sid: String,
+
+ /**
+ * An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity
+ * Service API's POST /validate/email/submitToken endpoint (without the requirement for an access token).
+ * The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.
+ *
+ * If this field is not present, the client can assume that verification will happen without the client's involvement provided
+ * the homeserver advertises this specification version in the /versions response (ie: r0.5.0).
+ */
+ @Json(name = "submit_url")
+ val submitUrl: String? = null,
+
+ /* ==========================================================================================
+ * It seems that the homeserver is sending more data, we may need it
+ * ========================================================================================== */
+
+ @Json(name = "msisdn")
+ val msisdn: String? = null,
+
+ @Json(name = "intl_fmt")
+ val formattedMsisdn: String? = null,
+
+ @Json(name = "success")
+ val success: Boolean? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt
new file mode 100644
index 0000000000..c844c8ca6f
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.awaitTransaction
+import java.util.UUID
+import javax.inject.Inject
+
+internal abstract class AddThreePidTask : Task {
+ data class Params(
+ val threePid: ThreePid
+ )
+}
+
+internal class DefaultAddThreePidTask @Inject constructor(
+ private val profileAPI: ProfileAPI,
+ @SessionDatabase private val monarchy: Monarchy,
+ private val pendingThreePidMapper: PendingThreePidMapper,
+ private val eventBus: EventBus) : AddThreePidTask() {
+
+ override suspend fun execute(params: Params) {
+ when (params.threePid) {
+ is ThreePid.Email -> addEmail(params.threePid)
+ is ThreePid.Msisdn -> addMsisdn(params.threePid)
+ }
+ }
+
+ private suspend fun addEmail(threePid: ThreePid.Email) {
+ val clientSecret = UUID.randomUUID().toString()
+ val sendAttempt = 1
+
+ val result = executeRequest(eventBus) {
+ val body = AddEmailBody(
+ clientSecret = clientSecret,
+ email = threePid.email,
+ sendAttempt = sendAttempt
+ )
+ apiCall = profileAPI.addEmail(body)
+ }
+
+ // Store as a pending three pid
+ monarchy.awaitTransaction { realm ->
+ PendingThreePid(
+ threePid = threePid,
+ clientSecret = clientSecret,
+ sendAttempt = sendAttempt,
+ sid = result.sid,
+ submitUrl = null
+ )
+ .let { pendingThreePidMapper.map(it) }
+ .let { realm.copyToRealm(it) }
+ }
+ }
+
+ private suspend fun addMsisdn(threePid: ThreePid.Msisdn) {
+ val clientSecret = UUID.randomUUID().toString()
+ val sendAttempt = 1
+
+ // Get country code and national number from the phone number
+ val phoneNumber = threePid.msisdn
+ val phoneNumberUtil = PhoneNumberUtil.getInstance()
+ val parsedNumber = phoneNumberUtil.parse(phoneNumber, null)
+ val countryCode = parsedNumber.countryCode
+ val country = phoneNumberUtil.getRegionCodeForCountryCode(countryCode)
+
+ val result = executeRequest(eventBus) {
+ val body = AddMsisdnBody(
+ clientSecret = clientSecret,
+ country = country,
+ phoneNumber = parsedNumber.nationalNumber.toString(),
+ sendAttempt = sendAttempt
+ )
+ apiCall = profileAPI.addMsisdn(body)
+ }
+
+ // Store as a pending three pid
+ monarchy.awaitTransaction { realm ->
+ PendingThreePid(
+ threePid = threePid,
+ clientSecret = clientSecret,
+ sendAttempt = sendAttempt,
+ sid = result.sid,
+ submitUrl = result.submitUrl
+ )
+ .let { pendingThreePidMapper.map(it) }
+ .let { realm.copyToRealm(it) }
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
index 633b047994..97212a8687 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
@@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.profile.ProfileService
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
import org.matrix.android.sdk.internal.database.model.UserThreePidEntity
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.content.FileUploader
@@ -44,6 +45,11 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
private val getProfileInfoTask: GetProfileInfoTask,
private val setDisplayNameTask: SetDisplayNameTask,
private val setAvatarUrlTask: SetAvatarUrlTask,
+ private val addThreePidTask: AddThreePidTask,
+ private val validateSmsCodeTask: ValidateSmsCodeTask,
+ private val finalizeAddingThreePidTask: FinalizeAddingThreePidTask,
+ private val deleteThreePidTask: DeleteThreePidTask,
+ private val pendingThreePidMapper: PendingThreePidMapper,
private val fileUploader: FileUploader) : ProfileService {
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback>): Cancelable {
@@ -116,9 +122,7 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
override fun getThreePidsLive(refreshData: Boolean): LiveData> {
if (refreshData) {
// Force a refresh of the values
- refreshUserThreePidsTask
- .configureWith()
- .executeBy(taskExecutor)
+ refreshThreePids()
}
return monarchy.findAllMappedWithChanges(
@@ -126,6 +130,95 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
{ it.asDomain() }
)
}
+
+ private fun refreshThreePids() {
+ refreshUserThreePidsTask
+ .configureWith()
+ .executeBy(taskExecutor)
+ }
+
+ override fun getPendingThreePids(): List {
+ return monarchy.fetchAllMappedSync(
+ { it.where() },
+ { pendingThreePidMapper.map(it).threePid }
+ )
+ }
+
+ override fun getPendingThreePidsLive(): LiveData> {
+ return monarchy.findAllMappedWithChanges(
+ { it.where() },
+ { pendingThreePidMapper.map(it).threePid }
+ )
+ }
+
+ override fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback): Cancelable {
+ return addThreePidTask
+ .configureWith(AddThreePidTask.Params(threePid)) {
+ callback = matrixCallback
+ }
+ .executeBy(taskExecutor)
+ }
+
+ override fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback): Cancelable {
+ return validateSmsCodeTask
+ .configureWith(ValidateSmsCodeTask.Params(threePid, code)) {
+ callback = matrixCallback
+ }
+ .executeBy(taskExecutor)
+ }
+
+ override fun finalizeAddingThreePid(threePid: ThreePid,
+ uiaSession: String?,
+ accountPassword: String?,
+ matrixCallback: MatrixCallback): Cancelable {
+ return finalizeAddingThreePidTask
+ .configureWith(FinalizeAddingThreePidTask.Params(
+ threePid = threePid,
+ session = uiaSession,
+ accountPassword = accountPassword,
+ userWantsToCancel = false
+ )) {
+ callback = alsoRefresh(matrixCallback)
+ }
+ .executeBy(taskExecutor)
+ }
+
+ override fun cancelAddingThreePid(threePid: ThreePid, matrixCallback: MatrixCallback): Cancelable {
+ return finalizeAddingThreePidTask
+ .configureWith(FinalizeAddingThreePidTask.Params(
+ threePid = threePid,
+ session = null,
+ accountPassword = null,
+ userWantsToCancel = true
+ )) {
+ callback = alsoRefresh(matrixCallback)
+ }
+ .executeBy(taskExecutor)
+ }
+
+ /**
+ * Wrap the callback to fetch 3Pids from the server in case of success
+ */
+ private fun alsoRefresh(callback: MatrixCallback): MatrixCallback {
+ return object : MatrixCallback {
+ override fun onFailure(failure: Throwable) {
+ callback.onFailure(failure)
+ }
+
+ override fun onSuccess(data: Unit) {
+ refreshThreePids()
+ callback.onSuccess(data)
+ }
+ }
+ }
+
+ override fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback): Cancelable {
+ return deleteThreePidTask
+ .configureWith(DeleteThreePidTask.Params(threePid)) {
+ callback = alsoRefresh(matrixCallback)
+ }
+ .executeBy(taskExecutor)
+ }
}
private fun UserThreePidEntity.asDomain(): ThreePid {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt
new file mode 100644
index 0000000000..e7d4568f8b
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class DeleteThreePidBody(
+ /**
+ * Required. The medium of the third party identifier being removed. One of: ["email", "msisdn"]
+ */
+ @Json(name = "medium") val medium: String,
+ /**
+ * Required. The third party address being removed.
+ */
+ @Json(name = "address") val address: String
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt
new file mode 100644
index 0000000000..3817277a9d
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class DeleteThreePidResponse(
+ /**
+ * Required. An indicator as to whether or not the homeserver was able to unbind the 3PID from
+ * the identity server. success indicates that the identity server has unbound the identifier
+ * whereas no-support indicates that the identity server refuses to support the request or the
+ * homeserver was not able to determine an identity server to unbind from. One of: ["no-support", "success"]
+ */
+ @Json(name = "id_server_unbind_result")
+ val idServerUnbindResult: String? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt
new file mode 100644
index 0000000000..69ff7d82da
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.api.session.identity.toMedium
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import javax.inject.Inject
+
+internal abstract class DeleteThreePidTask : Task {
+ data class Params(
+ val threePid: ThreePid
+ )
+}
+
+internal class DefaultDeleteThreePidTask @Inject constructor(
+ private val profileAPI: ProfileAPI,
+ private val eventBus: EventBus) : DeleteThreePidTask() {
+
+ override suspend fun execute(params: Params) {
+ executeRequest(eventBus) {
+ val body = DeleteThreePidBody(
+ medium = params.threePid.toMedium(),
+ address = params.threePid.value
+ )
+ apiCall = profileAPI.deleteThreePid(body)
+ }
+
+ // We do not really care about the result for the moment
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt
new file mode 100644
index 0000000000..73e9b39cea
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth
+
+@JsonClass(generateAdapter = true)
+internal data class FinalizeAddThreePidBody(
+ /**
+ * Required. The client secret used in the session with the homeserver.
+ */
+ @Json(name = "client_secret")
+ val clientSecret: String,
+
+ /**
+ * Required. The session identifier given by the homeserver.
+ */
+ @Json(name = "sid")
+ val sid: String,
+
+ /**
+ * Additional authentication information for the user-interactive authentication API.
+ */
+ @Json(name = "auth")
+ val auth: UserPasswordAuth?
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt
new file mode 100644
index 0000000000..3886b926ba
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.di.UserId
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.awaitTransaction
+import javax.inject.Inject
+
+internal abstract class FinalizeAddingThreePidTask : Task {
+ data class Params(
+ val threePid: ThreePid,
+ val session: String?,
+ val accountPassword: String?,
+ val userWantsToCancel: Boolean
+ )
+}
+
+internal class DefaultFinalizeAddingThreePidTask @Inject constructor(
+ private val profileAPI: ProfileAPI,
+ @SessionDatabase private val monarchy: Monarchy,
+ private val pendingThreePidMapper: PendingThreePidMapper,
+ @UserId private val userId: String,
+ private val eventBus: EventBus) : FinalizeAddingThreePidTask() {
+
+ override suspend fun execute(params: Params) {
+ if (params.userWantsToCancel.not()) {
+ // Get the required pending data
+ val pendingThreePids = monarchy.fetchAllMappedSync(
+ { it.where(PendingThreePidEntity::class.java) },
+ { pendingThreePidMapper.map(it) }
+ )
+ .firstOrNull { it.threePid == params.threePid }
+ ?: throw IllegalArgumentException("unknown threepid")
+
+ try {
+ executeRequest(eventBus) {
+ val body = FinalizeAddThreePidBody(
+ clientSecret = pendingThreePids.clientSecret,
+ sid = pendingThreePids.sid,
+ auth = if (params.session != null && params.accountPassword != null) {
+ UserPasswordAuth(
+ session = params.session,
+ user = userId,
+ password = params.accountPassword
+ )
+ } else null
+ )
+ apiCall = profileAPI.finalizeAddThreePid(body)
+ }
+ } catch (throwable: Throwable) {
+ throw throwable.toRegistrationFlowResponse()
+ ?.let { Failure.RegistrationFlowError(it) }
+ ?: throwable
+ }
+ }
+
+ cleanupDatabase(params)
+ }
+
+ private suspend fun cleanupDatabase(params: Params) {
+ // Delete the pending three pid
+ monarchy.awaitTransaction { realm ->
+ realm.where(PendingThreePidEntity::class.java)
+ .equalTo(PendingThreePidEntityFields.EMAIL, params.threePid.value)
+ .or()
+ .equalTo(PendingThreePidEntityFields.MSISDN, params.threePid.value)
+ .findAll()
+ .deleteAllFromRealm()
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt
new file mode 100644
index 0000000000..af7e217d47
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import org.matrix.android.sdk.api.session.identity.ThreePid
+
+internal data class PendingThreePid(
+ val threePid: ThreePid,
+ val clientSecret: String,
+ val sendAttempt: Int,
+ // For Msisdn and Email
+ val sid: String,
+ // For Msisdn only
+ val submitUrl: String?
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt
new file mode 100644
index 0000000000..b1877027ed
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import javax.inject.Inject
+
+internal class PendingThreePidMapper @Inject constructor() {
+
+ fun map(entity: PendingThreePidEntity): PendingThreePid {
+ return PendingThreePid(
+ threePid = entity.email?.let { ThreePid.Email(it) }
+ ?: entity.msisdn?.let { ThreePid.Msisdn(it) }
+ ?: error("Invalid data"),
+ clientSecret = entity.clientSecret,
+ sendAttempt = entity.sendAttempt,
+ sid = entity.sid,
+ submitUrl = entity.submitUrl
+ )
+ }
+
+ fun map(domain: PendingThreePid): PendingThreePidEntity {
+ return PendingThreePidEntity(
+ email = domain.threePid.takeIf { it is ThreePid.Email }?.value,
+ msisdn = domain.threePid.takeIf { it is ThreePid.Msisdn }?.value,
+ clientSecret = domain.clientSecret,
+ sendAttempt = domain.sendAttempt,
+ sid = domain.sid,
+ submitUrl = domain.submitUrl
+ )
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
index 31e1f09bbd..4e2f518c5a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
@@ -19,6 +19,8 @@
package org.matrix.android.sdk.internal.session.profile
import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.internal.auth.registration.SuccessResult
+import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
import org.matrix.android.sdk.internal.network.NetworkConstants
import retrofit2.Call
import retrofit2.http.Body
@@ -26,9 +28,9 @@ import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
+import retrofit2.http.Url
internal interface ProfileAPI {
-
/**
* Get the combined profile information for this user.
* This API may be used to fetch the user's own profile information or other users; either locally or on remote homeservers.
@@ -71,4 +73,35 @@ internal interface ProfileAPI {
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "account/3pid/unbind")
fun unbindThreePid(@Body body: UnbindThreePidBody): Call
+
+ /**
+ * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-email-requesttoken
+ */
+ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/email/requestToken")
+ fun addEmail(@Body body: AddEmailBody): Call
+
+ /**
+ * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-msisdn-requesttoken
+ */
+ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/msisdn/requestToken")
+ fun addMsisdn(@Body body: AddMsisdnBody): Call
+
+ /**
+ * Validate Msisdn code (same model than for Identity server API)
+ */
+ @POST
+ fun validateMsisdn(@Url url: String,
+ @Body params: ValidationCodeBody): Call
+
+ /**
+ * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-add
+ */
+ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/add")
+ fun finalizeAddThreePid(@Body body: FinalizeAddThreePidBody): Call
+
+ /**
+ * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-delete
+ */
+ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/delete")
+ fun deleteThreePid(@Body body: DeleteThreePidBody): Call
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
index 57a86d03e0..ae7ae7a6f3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
@@ -58,4 +58,16 @@ internal abstract class ProfileModule {
@Binds
abstract fun bindSetAvatarUrlTask(task: DefaultSetAvatarUrlTask): SetAvatarUrlTask
+
+ @Binds
+ abstract fun bindAddThreePidTask(task: DefaultAddThreePidTask): AddThreePidTask
+
+ @Binds
+ abstract fun bindValidateSmsCodeTask(task: DefaultValidateSmsCodeTask): ValidateSmsCodeTask
+
+ @Binds
+ abstract fun bindFinalizeAddingThreePidTask(task: DefaultFinalizeAddingThreePidTask): FinalizeAddingThreePidTask
+
+ @Binds
+ abstract fun bindDeleteThreePidTask(task: DefaultDeleteThreePidTask): DeleteThreePidTask
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt
new file mode 100644
index 0000000000..b11955b96a
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.profile
+
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.auth.registration.SuccessResult
+import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import javax.inject.Inject
+
+internal interface ValidateSmsCodeTask : Task {
+ data class Params(
+ val threePid: ThreePid.Msisdn,
+ val code: String
+ )
+}
+
+internal class DefaultValidateSmsCodeTask @Inject constructor(
+ private val profileAPI: ProfileAPI,
+ @SessionDatabase
+ private val monarchy: Monarchy,
+ private val pendingThreePidMapper: PendingThreePidMapper,
+ private val eventBus: EventBus
+) : ValidateSmsCodeTask {
+
+ override suspend fun execute(params: ValidateSmsCodeTask.Params) {
+ // Search the pending ThreePid
+ val pendingThreePids = monarchy.fetchAllMappedSync(
+ { it.where(PendingThreePidEntity::class.java) },
+ { pendingThreePidMapper.map(it) }
+ )
+ .firstOrNull { it.threePid == params.threePid }
+ ?: throw IllegalArgumentException("unknown threepid")
+
+ val url = pendingThreePids.submitUrl ?: throw IllegalArgumentException("invalid threepid")
+ val body = ValidationCodeBody(
+ clientSecret = pendingThreePids.clientSecret,
+ sid = pendingThreePids.sid,
+ code = params.code
+ )
+ val result = executeRequest(eventBus) {
+ apiCall = profileAPI.validateMsisdn(url, body)
+ }
+
+ if (!result.isSuccess()) {
+ throw Failure.SuccessError
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
index 7f21ee84f6..700507735b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
@@ -20,6 +20,8 @@ package org.matrix.android.sdk.internal.session.room
import dagger.Binds
import dagger.Module
import dagger.Provides
+import org.commonmark.parser.Parser
+import org.commonmark.renderer.html.HtmlRenderer
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
import org.matrix.android.sdk.api.session.room.RoomService
@@ -75,9 +77,6 @@ import org.matrix.android.sdk.internal.session.room.typing.DefaultSendTypingTask
import org.matrix.android.sdk.internal.session.room.typing.SendTypingTask
import org.matrix.android.sdk.internal.session.room.uploads.DefaultGetUploadsTask
import org.matrix.android.sdk.internal.session.room.uploads.GetUploadsTask
-import org.commonmark.parser.Parser
-import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
import retrofit2.Retrofit
@Module
@@ -105,14 +104,6 @@ internal abstract class RoomModule {
.builder()
.build()
}
-
- @Provides
- @JvmStatic
- fun providesTextContentRenderer(): TextContentRenderer {
- return TextContentRenderer
- .builder()
- .build()
- }
}
@Binds
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt
new file mode 100644
index 0000000000..0b79b93cf6
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.room.send
+
+import org.matrix.android.sdk.internal.session.SessionScope
+import javax.inject.Inject
+
+/**
+ * We cannot use work manager cancellation mechanism because cancelling a work will just ignore
+ * any follow up send that was already queued.
+ * We use this class to track cancel requests, the workers will look for this to check for cancellation request
+ * and just ignore the work request and continue by returning success.
+ *
+ * Known limitation, for now requests are not persisted
+ */
+@SessionScope
+internal class CancelSendTracker @Inject constructor() {
+
+ data class Request(
+ val localId: String,
+ val roomId: String
+ )
+
+ private val cancellingRequests = ArrayList()
+
+ fun markLocalEchoForCancel(eventId: String, roomId: String) {
+ synchronized(cancellingRequests) {
+ cancellingRequests.add(Request(eventId, roomId))
+ }
+ }
+
+ fun isCancelRequestedFor(eventId: String?, roomId: String?): Boolean {
+ val index = synchronized(cancellingRequests) {
+ cancellingRequests.indexOfFirst { it.localId == eventId && it.roomId == roomId }
+ }
+ return index != -1
+ }
+
+ fun markCancelled(eventId: String, roomId: String) {
+ synchronized(cancellingRequests) {
+ val index = cancellingRequests.indexOfFirst { it.localId == eventId && it.roomId == roomId }
+ if (index != -1) {
+ cancellingRequests.removeAt(index)
+ }
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
index d6fa6775ee..95cd1c699c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
@@ -17,24 +17,35 @@
package org.matrix.android.sdk.internal.session.room.send
+import android.net.Uri
import androidx.work.BackoffPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.Operation
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
+import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.Event
-import org.matrix.android.sdk.api.session.events.model.isImageMessage
+import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
import org.matrix.android.sdk.api.session.events.model.isTextMessage
+import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
import org.matrix.android.sdk.api.session.room.model.message.OptionItem
+import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
import org.matrix.android.sdk.api.session.room.send.SendService
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.CancelableBag
import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.api.util.NoOpCancellable
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.WorkManagerProvider
import org.matrix.android.sdk.internal.session.content.UploadContentWorker
@@ -44,7 +55,6 @@ import org.matrix.android.sdk.internal.util.CancelableWork
import org.matrix.android.sdk.internal.worker.AlwaysSuccessfulWorker
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
import org.matrix.android.sdk.internal.worker.startChain
-import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@@ -60,7 +70,8 @@ internal class DefaultSendService @AssistedInject constructor(
private val cryptoService: CryptoService,
private val taskExecutor: TaskExecutor,
private val localEchoRepository: LocalEchoRepository,
- private val roomEventSender: RoomEventSender
+ private val roomEventSender: RoomEventSender,
+ private val cancelSendTracker: CancelSendTracker
) : SendService {
@AssistedInject.Factory
@@ -127,48 +138,83 @@ internal class DefaultSendService @AssistedInject constructor(
.let { timelineSendEventWorkCommon.postWork(roomId, it) }
}
- override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? {
+ override fun resendTextMessage(localEcho: TimelineEvent): Cancelable {
if (localEcho.root.isTextMessage() && localEcho.root.sendState.hasFailed()) {
localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
return sendEvent(localEcho.root)
}
- return null
+ return NoOpCancellable
}
- override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable? {
- if (localEcho.root.isImageMessage() && localEcho.root.sendState.hasFailed()) {
- // TODO this need a refactoring of attachement sending
-// val clearContent = localEcho.root.getClearContent()
-// val messageContent = clearContent?.toModel() ?: return null
-// when (messageContent.type) {
-// MessageType.MSGTYPE_IMAGE -> {
-// val imageContent = clearContent.toModel() ?: return null
-// val url = imageContent.url ?: return null
-// if (url.startsWith("mxc://")) {
-// //TODO
-// } else {
-// //The image has not yet been sent
-// val attachmentData = ContentAttachmentData(
-// size = imageContent.info!!.size.toLong(),
-// mimeType = imageContent.info.mimeType!!,
-// width = imageContent.info.width.toLong(),
-// height = imageContent.info.height.toLong(),
-// name = imageContent.body,
-// path = imageContent.url,
-// type = ContentAttachmentData.Type.IMAGE
-// )
-// monarchy.runTransactionSync {
-// EventEntity.where(it,eventId = localEcho.root.eventId ?: "").findFirst()?.let {
-// it.sendState = SendState.UNSENT
-// }
-// }
-// return internalSendMedia(localEcho.root,attachmentData)
-// }
-// }
-// }
- return null
+ override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable {
+ if (localEcho.root.sendState.hasFailed()) {
+ val clearContent = localEcho.root.getClearContent()
+ val messageContent = clearContent?.toModel() as? MessageWithAttachmentContent ?: return NoOpCancellable
+
+ val url = messageContent.getFileUrl() ?: return NoOpCancellable
+ if (url.startsWith("mxc://")) {
+ // We need to resend only the message as the attachment is ok
+ localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+ return sendEvent(localEcho.root)
+ }
+
+ // we need to resend the media
+ return when (messageContent) {
+ is MessageImageContent -> {
+ // The image has not yet been sent
+ val attachmentData = ContentAttachmentData(
+ size = messageContent.info!!.size.toLong(),
+ mimeType = messageContent.info.mimeType!!,
+ width = messageContent.info.width.toLong(),
+ height = messageContent.info.height.toLong(),
+ name = messageContent.body,
+ queryUri = Uri.parse(messageContent.url),
+ type = ContentAttachmentData.Type.IMAGE
+ )
+ localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+ internalSendMedia(listOf(localEcho.root), attachmentData, true)
+ }
+ is MessageVideoContent -> {
+ val attachmentData = ContentAttachmentData(
+ size = messageContent.videoInfo?.size ?: 0L,
+ mimeType = messageContent.mimeType,
+ width = messageContent.videoInfo?.width?.toLong(),
+ height = messageContent.videoInfo?.height?.toLong(),
+ duration = messageContent.videoInfo?.duration?.toLong(),
+ name = messageContent.body,
+ queryUri = Uri.parse(messageContent.url),
+ type = ContentAttachmentData.Type.VIDEO
+ )
+ localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+ internalSendMedia(listOf(localEcho.root), attachmentData, true)
+ }
+ is MessageFileContent -> {
+ val attachmentData = ContentAttachmentData(
+ size = messageContent.info!!.size,
+ mimeType = messageContent.info.mimeType!!,
+ name = messageContent.body,
+ queryUri = Uri.parse(messageContent.url),
+ type = ContentAttachmentData.Type.FILE
+ )
+ localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+ internalSendMedia(listOf(localEcho.root), attachmentData, true)
+ }
+ is MessageAudioContent -> {
+ val attachmentData = ContentAttachmentData(
+ size = messageContent.audioInfo?.size ?: 0,
+ duration = messageContent.audioInfo?.duration?.toLong() ?: 0L,
+ mimeType = messageContent.audioInfo?.mimeType,
+ name = messageContent.body,
+ queryUri = Uri.parse(messageContent.url),
+ type = ContentAttachmentData.Type.AUDIO
+ )
+ localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+ internalSendMedia(listOf(localEcho.root), attachmentData, true)
+ }
+ else -> NoOpCancellable
+ }
}
- return null
+ return NoOpCancellable
}
override fun deleteFailedEcho(localEcho: TimelineEvent) {
@@ -196,16 +242,34 @@ internal class DefaultSendService @AssistedInject constructor(
}
}
+ override fun cancelSend(eventId: String) {
+ cancelSendTracker.markLocalEchoForCancel(eventId, roomId)
+ taskExecutor.executorScope.launch {
+ localEchoRepository.deleteFailedEcho(roomId, eventId)
+ }
+ }
+
override fun resendAllFailedMessages() {
taskExecutor.executorScope.launch {
val eventsToResend = localEchoRepository.getAllFailedEventsToResend(roomId)
eventsToResend.forEach {
- sendEvent(it)
+ if (it.root.isTextMessage()) {
+ resendTextMessage(it)
+ } else if (it.root.isAttachmentMessage()) {
+ resendMediaMessage(it)
+ }
}
- localEchoRepository.updateSendState(roomId, eventsToResend.mapNotNull { it.eventId }, SendState.UNSENT)
+ localEchoRepository.updateSendState(roomId, eventsToResend.map { it.eventId }, SendState.UNSENT)
}
}
+// override fun failAllPendingMessages() {
+// taskExecutor.executorScope.launch {
+// val eventsToResend = localEchoRepository.getAllEventsWithStates(roomId, SendState.PENDING_STATES)
+// localEchoRepository.updateSendState(roomId, eventsToResend.map { it.eventId }, SendState.UNDELIVERED)
+// }
+// }
+
override fun sendMedia(attachment: ContentAttachmentData,
compressBeforeSending: Boolean,
roomIds: Set): Cancelable {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
index f878df52b2..6b2a2ab115 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
@@ -54,6 +54,7 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
@Inject lateinit var crypto: CryptoService
@Inject lateinit var localEchoRepository: LocalEchoRepository
+ @Inject lateinit var cancelSendTracker: CancelSendTracker
override suspend fun doWork(): Result {
Timber.v("Start Encrypt work")
@@ -61,7 +62,7 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
?: return Result.success()
.also { Timber.e("Unable to parse work parameters") }
- Timber.v("Start Encrypt work for event ${params.event.eventId}")
+ Timber.v("## SendEvent: Start Encrypt work for event ${params.event.eventId}")
if (params.lastFailureMessage != null) {
// Transmit the error
return Result.success(inputData)
@@ -75,6 +76,12 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
if (localEvent.eventId == null) {
return Result.success()
}
+
+ if (cancelSendTracker.isCancelRequestedFor(localEvent.eventId, localEvent.roomId)) {
+ return Result.success()
+ .also { Timber.e("## SendEvent: Event sending has been cancelled ${localEvent.eventId}") }
+ }
+
localEchoRepository.updateSendState(localEvent.eventId, SendState.ENCRYPTING)
val localMutableContent = localEvent.content?.toMutableMap() ?: mutableMapOf()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
index a9859136ad..b3188883c0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
@@ -30,7 +30,6 @@ import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult
import org.matrix.android.sdk.internal.database.helper.nextId
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
-import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.mapper.toEntity
import org.matrix.android.sdk.internal.database.model.EventEntity
import org.matrix.android.sdk.internal.database.model.EventInsertEntity
@@ -88,7 +87,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
}
fun updateSendState(eventId: String, sendState: SendState) {
- Timber.v("Update local state of $eventId to ${sendState.name}")
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Update local state of $eventId to ${sendState.name}")
monarchy.writeAsync { realm ->
val sendingEventEntity = EventEntity.where(realm, eventId).findFirst()
if (sendingEventEntity != null) {
@@ -114,9 +113,13 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
}
suspend fun deleteFailedEcho(roomId: String, localEcho: TimelineEvent) {
+ deleteFailedEcho(roomId, localEcho.eventId)
+ }
+
+ suspend fun deleteFailedEcho(roomId: String, eventId: String?) {
monarchy.awaitTransaction { realm ->
- TimelineEventEntity.where(realm, roomId = roomId, eventId = localEcho.root.eventId ?: "").findFirst()?.deleteFromRealm()
- EventEntity.where(realm, eventId = localEcho.root.eventId ?: "").findFirst()?.deleteFromRealm()
+ TimelineEventEntity.where(realm, roomId = roomId, eventId = eventId ?: "").findFirst()?.deleteFromRealm()
+ EventEntity.where(realm, eventId = eventId ?: "").findFirst()?.deleteFromRealm()
roomSummaryUpdater.updateSendingInformation(realm, roomId)
}
}
@@ -142,45 +145,47 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
}
}
- fun getAllFailedEventsToResend(roomId: String): List {
+ fun getAllFailedEventsToResend(roomId: String): List {
+ return getAllEventsWithStates(roomId, SendState.HAS_FAILED_STATES)
+ }
+
+ fun getAllEventsWithStates(roomId: String, states : List): List {
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
TimelineEventEntity
- .findAllInRoomWithSendStates(realm, roomId, SendState.HAS_FAILED_STATES)
+ .findAllInRoomWithSendStates(realm, roomId, states)
.sortedByDescending { it.displayIndex }
- .mapNotNull { it.root?.asDomain() }
+ .mapNotNull { it?.let { timelineEventMapper.map(it) } }
.filter { event ->
- when (event.getClearType()) {
+ when (event.root.getClearType()) {
EventType.MESSAGE,
EventType.REDACTION,
EventType.REACTION -> {
- val content = event.getClearContent().toModel()
+ val content = event.root.getClearContent().toModel()
if (content != null) {
when (content.msgType) {
MessageType.MSGTYPE_EMOTE,
MessageType.MSGTYPE_NOTICE,
MessageType.MSGTYPE_LOCATION,
- MessageType.MSGTYPE_TEXT -> {
- true
- }
+ MessageType.MSGTYPE_TEXT,
MessageType.MSGTYPE_FILE,
MessageType.MSGTYPE_VIDEO,
MessageType.MSGTYPE_IMAGE,
MessageType.MSGTYPE_AUDIO -> {
// need to resend the attachment
- false
+ true
}
else -> {
- Timber.e("Cannot resend message ${event.type} / ${content.msgType}")
+ Timber.e("Cannot resend message ${event.root.getClearType()} / ${content.msgType}")
false
}
}
} else {
- Timber.e("Unsupported message to resend ${event.type}")
+ Timber.e("Unsupported message to resend ${event.root.getClearType()}")
false
}
}
else -> {
- Timber.e("Unsupported message to resend ${event.type}")
+ Timber.e("Unsupported message to resend ${event.root.getClearType()}")
false
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
index 3390d9dc79..f80285574e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
@@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.room.send
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
import javax.inject.Inject
/**
@@ -29,11 +28,10 @@ import javax.inject.Inject
*/
internal class MarkdownParser @Inject constructor(
private val parser: Parser,
- private val htmlRenderer: HtmlRenderer,
- private val textContentRenderer: TextContentRenderer
+ private val htmlRenderer: HtmlRenderer
) {
- private val mdSpecialChars = "[`_\\-\\*>\\.\\[\\]#~]".toRegex()
+ private val mdSpecialChars = "[`_\\-*>.\\[\\]#~]".toRegex()
fun parse(text: String): TextContent {
// If no special char are detected, just return plain text
@@ -54,8 +52,8 @@ internal class MarkdownParser @Inject constructor(
return if (isFormattedTextPertinent(text, cleanHtmlText)) {
// According to https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes:
// The plain text version of the HTML should be provided in the body.
- val plainText = textContentRenderer.render(document)
- TextContent(plainText, cleanHtmlText.postTreatment())
+ // But it caused too many problems so it has been removed in #2002
+ TextContent(text, cleanHtmlText.postTreatment())
} else {
TextContent(text)
}
@@ -72,6 +70,7 @@ internal class MarkdownParser @Inject constructor(
// Remove extra space before and after the content
.trim()
// There is no need to include new line in an html-like source
- .replace("\n", "")
+ // But new line can be in embedded code block, so do not remove them
+ // .replace("\n", "")
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
index ead2dc9377..8e8d24c227 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
@@ -58,7 +58,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
@Inject lateinit var localEchoRepository: LocalEchoRepository
override suspend fun doWork(): Result {
- Timber.v("Start dispatch sending multiple event work")
+ Timber.v("## SendEvent: Start dispatch sending multiple event work")
val params = WorkerParamsFactory.fromData(inputData)
?: return Result.success()
.also { Timber.e("Unable to parse work parameters") }
@@ -72,18 +72,21 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
}
// Transmit the error if needed?
return Result.success(inputData)
- .also { Timber.e("Work cancelled due to input error from parent") }
+ .also { Timber.e("## SendEvent: Work cancelled due to input error from parent ${params.lastFailureMessage}") }
}
// Create a work for every event
params.events.forEach { event ->
if (params.isEncrypted) {
- Timber.v("Send event in encrypted room")
+ localEchoRepository.updateSendState(event.eventId ?: "", SendState.ENCRYPTING)
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule encrypt and send event ${event.eventId}")
val encryptWork = createEncryptEventWork(params.sessionId, event, true)
// Note that event will be replaced by the result of the previous work
val sendWork = createSendEventWork(params.sessionId, event, false)
timelineSendEventWorkCommon.postSequentialWorks(event.roomId!!, encryptWork, sendWork)
} else {
+ localEchoRepository.updateSendState(event.eventId ?: "", SendState.SENDING)
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule send event ${event.eventId}")
val sendWork = createSendEventWork(params.sessionId, event, true)
timelineSendEventWorkCommon.postWork(event.roomId!!, sendWork)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
index e46adeb9c1..6085459a08 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
@@ -39,13 +39,16 @@ internal class RoomEventSender @Inject constructor(
) {
fun sendEvent(event: Event): Cancelable {
// Encrypted room handling
- return if (cryptoService.isRoomEncrypted(event.roomId ?: "")) {
- Timber.v("Send event in encrypted room")
+ return if (cryptoService.isRoomEncrypted(event.roomId ?: "")
+ && !event.isEncrypted() // In case of resend where it's already encrypted so skip to send
+ ) {
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule encrypt and send event ${event.eventId}")
val encryptWork = createEncryptEventWork(event, true)
// Note that event will be replaced by the result of the previous work
val sendWork = createSendEventWork(event, false)
timelineSendEventWorkCommon.postSequentialWorks(event.roomId ?: "", encryptWork, sendWork)
} else {
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule send event ${event.eventId}")
val sendWork = createSendEventWork(event, true)
timelineSendEventWorkCommon.postWork(event.roomId ?: "", sendWork)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
index 5da14f0a41..16acde7d16 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
@@ -34,7 +34,7 @@ import org.matrix.android.sdk.internal.worker.getSessionComponent
import timber.log.Timber
import javax.inject.Inject
-private const val MAX_NUMBER_OF_RETRY_BEFORE_FAILING = 3
+// private const val MAX_NUMBER_OF_RETRY_BEFORE_FAILING = 3
/**
* Possible previous worker: [EncryptEventWorker] or first worker
@@ -56,12 +56,12 @@ internal class SendEventWorker(context: Context,
@Inject lateinit var localEchoRepository: LocalEchoRepository
@Inject lateinit var roomAPI: RoomAPI
@Inject lateinit var eventBus: EventBus
+ @Inject lateinit var cancelSendTracker: CancelSendTracker
override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData(inputData)
?: return Result.success()
- .also { Timber.e("Unable to parse work parameters") }
-
+ .also { Timber.e("## SendEvent: Unable to parse work parameters") }
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
sessionComponent.inject(this)
@@ -75,22 +75,32 @@ internal class SendEventWorker(context: Context,
.also { Timber.e("Work cancelled due to bad input data") }
}
+ if (cancelSendTracker.isCancelRequestedFor(params.eventId, event.roomId)) {
+ return Result.success()
+ .also {
+ cancelSendTracker.markCancelled(event.eventId, event.roomId)
+ Timber.e("## SendEvent: Event sending has been cancelled ${params.eventId}")
+ }
+ }
+
if (params.lastFailureMessage != null) {
localEchoRepository.updateSendState(event.eventId, SendState.UNDELIVERED)
// Transmit the error
return Result.success(inputData)
.also { Timber.e("Work cancelled due to input error from parent") }
}
+
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] Send event ${params.eventId}")
return try {
sendEvent(event.eventId, event.roomId, event.type, event.content)
Result.success()
} catch (exception: Throwable) {
- // It does start from 0, we want it to stop if it fails the third time
- val currentAttemptCount = runAttemptCount + 1
- if (currentAttemptCount >= MAX_NUMBER_OF_RETRY_BEFORE_FAILING || !exception.shouldBeRetried()) {
+ if (/*currentAttemptCount >= MAX_NUMBER_OF_RETRY_BEFORE_FAILING ||**/ !exception.shouldBeRetried()) {
+ Timber.e("## SendEvent: [${System.currentTimeMillis()}] Send event Failed cannot retry ${params.eventId} > ${exception.localizedMessage}")
localEchoRepository.updateSendState(event.eventId, SendState.UNDELIVERED)
return Result.success()
} else {
+ Timber.e("## SendEvent: [${System.currentTimeMillis()}] Send event Failed schedule retry ${params.eventId} > ${exception.localizedMessage}")
Result.retry()
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
index b4c32c045e..a569b775a4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
@@ -115,6 +115,7 @@ internal class DefaultTimeline(
if (!results.isLoaded || !results.isValid) {
return@OrderedRealmCollectionChangeListener
}
+ Timber.v("## SendEvent: [${System.currentTimeMillis()}] DB update for room $roomId")
handleUpdates(results, changeSet)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
index d3124b68ca..3bc6a85cfb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
@@ -57,7 +57,7 @@ internal class TimelineSendEventWorkCommon @Inject constructor(
}
}
- fun postWork(roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND): Cancelable {
+ fun postWork(roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND_OR_REPLACE): Cancelable {
workManagerProvider.workManager
.beginUniqueWork(buildWorkName(roomId), policy, workRequest)
.enqueue()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt
new file mode 100644
index 0000000000..76e24c4e31
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.util
+
+/**
+ * Base64 URL conversion methods
+ */
+
+internal fun base64UrlToBase64(base64Url: String): String {
+ return base64Url.replace('-', '+')
+ .replace('_', '/')
+}
+
+internal fun base64ToBase64Url(base64: String): String {
+ return base64.replace("\n".toRegex(), "")
+ .replace("\\+".toRegex(), "-")
+ .replace('/', '_')
+ .replace("=", "")
+}
+
+internal fun base64ToUnpaddedBase64(base64: String): String {
+ return base64.replace("\n".toRegex(), "")
+ .replace("=", "")
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
index e20fe9a304..80ede5e884 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
@@ -97,7 +97,7 @@ internal class DefaultGetWellknownTask @Inject constructor(
// Success
val homeServerBaseUrl = wellKnown.homeServer?.baseURL
if (homeServerBaseUrl.isNullOrBlank()) {
- WellknownResult.FailPrompt
+ WellknownResult.FailPrompt(null, null)
} else {
if (homeServerBaseUrl.isValidUrl()) {
// Check that HS is a real one
@@ -120,11 +120,11 @@ internal class DefaultGetWellknownTask @Inject constructor(
is Failure.OtherServerError -> {
when (throwable.httpCode) {
HttpsURLConnection.HTTP_NOT_FOUND -> WellknownResult.Ignore
- else -> WellknownResult.FailPrompt
+ else -> WellknownResult.FailPrompt(null, null)
}
}
is MalformedJsonException, is EOFException -> {
- WellknownResult.FailPrompt
+ WellknownResult.FailPrompt(null, null)
}
else -> {
throw throwable
@@ -162,7 +162,7 @@ internal class DefaultGetWellknownTask @Inject constructor(
// All is ok
WellknownResult.Prompt(homeServerBaseUrl, identityServerBaseUrl, wellKnown)
} else {
- WellknownResult.FailError
+ WellknownResult.FailPrompt(homeServerBaseUrl, wellKnown)
}
} else {
WellknownResult.FailError
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_aeroplane.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_aeroplane.xml
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_headphones.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_headphones.xml
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_spanner.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_spanner.xml
diff --git a/matrix-sdk-android/src/main/res/values-az/strings.xml b/matrix-sdk-android/src/main/res/values-az/strings.xml
index 9c60dfafa7..1f366c647f 100644
--- a/matrix-sdk-android/src/main/res/values-az/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-az/strings.xml
@@ -79,72 +79,6 @@
Boş otaq
-
- It
- Pişik
- Aslan
- At
- Kərgədan
- Donuz
- Fil
- Dovşan
- Panda
- Xoruz
- Pinqvin
- Tısbağa
- Balıq
- Ahtapot
- Kəpənək
- Çiçək
- Ağac
- Kaktus
- Göbələk
- Qlobus
- Ay
- Bulud
- Atəş
- Banan
- Alma
- Çiyələk
- Qarğıdalı
- Pizza
- Tort
- Ürək
- Təbəssüm
- Robot
- Papaq
- Eynəklər
- Açar
- Santa
- Baş barmaqlar yuxarı
- Çətir
- Qum saatı
- Saat
- Hədiyyə
- Lampa
- Kitab
- Qələm
- Kağız sancağı
- Qayçı
- Qıfıl
- Açar
- Çəkic
- Telefon
- Bayraq
- Qatar
- Velosiped
- Təyyarə
- Raket
- Kubok
- Top
- Gitara
- Saz
- Zəng
- Anker
- Qulaqlıqlar
- Qovluq
- Sancaq
-
İlkin sinxronizasiya:
\nHesab idxal olunur…İlkin sinxronizasiya:
diff --git a/matrix-sdk-android/src/main/res/values-bg/strings.xml b/matrix-sdk-android/src/main/res/values-bg/strings.xml
index 07d59852f3..9654fd00b5 100644
--- a/matrix-sdk-android/src/main/res/values-bg/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-bg/strings.xml
@@ -78,70 +78,6 @@
Съобщение премахнато от %1$sПремахнато съобщение [причина: %1$s]Съобщение премахнато от %1$s [причина: %2$s]
- Куче
- Котка
- Лъв
- Кон
- Еднорог
- Прасе
- Слон
- Заек
- Панда
- Петел
- Пингвин
- Костенурка
- Риба
- Октопод
- Пеперуда
- Цвете
- Дърво
- Кактус
- Гъба
- Глобус
- Луна
- Облак
- Огън
- Банан
- Ябълка
- Ягода
- Царевица
- Пица
- Торта
- Сърце
- Усмивка
- Робот
- Шапка
- Очила
- Гаечен ключ
- Дядо Коледа
- Палец нагоре
- Чадър
- Пясъчен часовник
- Часовник
- Подарък
- Лампа
- Книга
- Молив
- Кламер
- Ножици
- Катинар
- Ключ
- Чук
- Телефон
- Знаме
- Влак
- Колело
- Самолет
- Ракета
- Трофей
- Топка
- Китара
- Тромпет
- Звънец
- Котва
- Слушалки
- Папка
- КарфицаНачална синхронизация:
\nИмпортиране на профил…
@@ -204,4 +140,16 @@
%s изпрати запитване за потвърждение на ключа ви, но клиентът ви не поддържа верифициране посредством чат. Ще трябва да използвате стария метод за верифициране на ключове.%1$s създаде стаята
+ Изпратихте снимка.
+ Изпратихте стикер.
+
+ Ваша покана
+ Създадохте стаята
+ Поканихте %1$s
+ Присъединихте се в стаята
+ Напуснахте стаята
+ Отхвърлихте поканата
+ Изгонихте %1$s
+ Отблокирахте %1$s
+ Блокирахте %1$s
diff --git a/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml b/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
index c8e70a9b20..5d38f0b3ee 100644
--- a/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
@@ -136,72 +136,6 @@
খালি কক্ষ
-
- কুকুর
- বেড়াল
- সিংহ
- ঘোড়া
- ইউনিকর্ন
- শূকর
- হাতি
- খরগোশ
- পান্ডা
- গৃহপালিত মোরগ
- পেংগুইন
- কচ্ছপ
- মাছ
- অক্টোপাস
- প্রজাপতি
- ফুল
- গাছ
- ফণীমনসা
- মাশরুম
- পৃথিবী
- চন্দ্র
- মেঘ
- আগুন
- কলা
- আপেল
- স্ট্রবেরি
- ভূট্টা
- পিজা
- কেক
- হৃদয়
- স্মাইলি
- রোবট
- টুপি
- চশমা
- রেঞ্চ
- সান্তা
- থাম্বস আপ
- ছাতা
- বালিঘড়ি
- ঘড়ি
- উপহার
- আলো বালব
- বই
- পেন্সিল
- পেপার ক্লিপ
- কাঁচি
- লক
- চাবি
- হাতুড়ি
- টেলিফোন
- পতাকা
- রেলগাড়ি
- সাইকেল
- বিমান
- রকেট
- ট্রফি
- বল
- গিটার
- ট্রাম্পেট
- ঘণ্টা
- নোঙ্গর
- হেডফোন
- ফোল্ডার
- পিন
-
প্রাথমিক সিঙ্ক:
\nঅ্যাকাউন্ট আমদানি করা হচ্ছে…প্রাথমিক সিঙ্ক:
@@ -288,8 +222,4 @@
%s আপনার কীটি যাচাই করার জন্য অনুরোধ করছে, তবে আপনার ক্লায়েন্ট ইন-চ্যাট কী যাচাইকরণ সমর্থন করে না। কীগুলি যাচাই করতে আপনাকে লিগ্যাসি কী যাচাইকরণ ব্যবহার করতে হবে।
- গ্রহণ
- পতন
- বন্ধ করুন
-
diff --git a/matrix-sdk-android/src/main/res/values-cs/strings.xml b/matrix-sdk-android/src/main/res/values-cs/strings.xml
index 44908c38f7..9e208f812a 100644
--- a/matrix-sdk-android/src/main/res/values-cs/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-cs/strings.xml
@@ -79,68 +79,7 @@
Zpráva byla smazána [důvod: %1$s]Zpráva smazána uživatelem %1$s [důvod: %2$s]Uživatel %1$s obnovil pozvánku do místnosti pro uživatele %2$s
- Kočka
- Lev
- Kůň
- Jednorožec
- Prase
- Slon
- Králík
- Panda
- Kohout
- Tučňák
- Želva
- Ryba
- Chobotnice
- Motýl
- Květina
- Strom
- Kaktus
- Houba
- Zeměkoule
- Měsíc
- Mrak
- Oheň
- Banán
- Jablko
- Jahoda
- Kukuřice
- Pizza
- Dort
- Srdce
- Smajlík
- Robot
- Klobouk
- Brýle
- Santa Klaus
- Zvednutý palec
- Deštník
- Přesípací hodiny
- Hodiny
- Dárek
- Žárovka
- Kniha
- Tužka
- Sponka
- Nůžky
- Zámek
- Klíč
- Kladivo
- Telefon
- Vlajka
- Vlak
- Jízdní kolo
- Letadlo
- Raketa
- Trofej
- Míč
- Kytara
- Trumpeta
- Zvon
- Kotva
- Sluchátka
- Desky
- Úvodní synchronizace:
+ Úvodní synchronizace:
\nImport účtu…Úvodní synchronizace:
\nImport klíčů
@@ -156,8 +95,6 @@
\nImport dat účtuOdesílání zprávy…
- Maticový klíč
- PřipínáčekÚvodní synchronizace:
\nImport pozvánek
diff --git a/matrix-sdk-android/src/main/res/values-de/strings.xml b/matrix-sdk-android/src/main/res/values-de/strings.xml
index 0c857e78ee..ae80edb47f 100644
--- a/matrix-sdk-android/src/main/res/values-de/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-de/strings.xml
@@ -89,73 +89,8 @@
Nachricht entfernt von %1$sNachricht entfernt [Grund: %1$s]Nachricht entfernt von %1$s [Grund: %2$s]
- Pizza
- Hund
- Katze
- Löwe
- Pferd
- Einhorn
- Schwein
- Elefant
- Kaninchen%s hat diesen Raum aufgewertet.
- Panda
- Hahn
- Pinguin
- Schildkröte
- Fisch
- Oktopus
- Schmetterling
- Blume
- Baum
- Kaktus
- Pilz
- Globus
- Mond
- Wolke
- Feuer
- Banane
- Apfel
- Erdbeere
- Mais
- Kuchen
- Herz
- Smiley
- Roboter
- Hut
- Brille
- Schraubenschlüssel
- Weihnachtsmann
- Daumen hoch
- Regenschirm
- Sanduhr
- Uhr
- Geschenk
- Glühbirne
- Buch
- Bleistift
- Büroklammer
- Schere
- Schloss
- Schlüssel
- Hammer
- Telefon
- Flagge
- Zug
- Fahrrad
- Flugzeug
- Rakete
- Pokal
- Ball
- Gitarre
- Trompete
- Glocke
- Anker
- Kopfhörer
- Ordner
- Stecknadel
-
Sende eine Nachricht…Sendewarteschlange leeren
@@ -297,10 +232,6 @@
Du hast Ende-zu-Ende-Verschlüsselung aktiviert.Du hast Ende-zu-Ende-Verschlüsselung aktiviert (unbekannter Algorithmus %1$s).
- Akzeptiere
- Ablehnen
- Anruf beenden
-
%s hat Daten gesendet, um einen Anruf zu starten.Du hast Daten geschickt, um eine Anruf zu starten.
diff --git a/matrix-sdk-android/src/main/res/values-de/strings_sas.xml b/matrix-sdk-android/src/main/res/values-de/strings_sas.xml
new file mode 100644
index 0000000000..108dedd1a5
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-de/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katze
+ Löwe
+ Pferd
+ Einhorn
+ Schwein
+ Elefant
+ Hase
+ Panda
+ Hahn
+ Pinguin
+ Schildkröte
+ Fisch
+ Oktopus
+ Schmetterling
+ Blume
+ Baum
+ Kaktus
+ Pilz
+ Globus
+ Mond
+ Wolke
+ Feuer
+ Banane
+ Apfel
+ Erdbeere
+ Korn
+ Pizza
+ Kuchen
+ Herz
+ Smiley
+ Roboter
+ Hut
+ Brille
+ Schraubenschlüssel
+ Nikolaus
+ Daumen Hoch
+ Regenschirm
+ Sanduhr
+ Wecker
+ Geschenk
+ Glühbirne
+ Buch
+ Bleistift
+ Büroklammer
+ Schere
+ Schloss
+ Schlüssel
+ Hammer
+ Telefon
+ Flagge
+ Zug
+ Fahrrad
+ Flugzeug
+ Rakete
+ Trophäe
+ Ball
+ Gitarre
+ Trompete
+ Glocke
+ Anker
+ Kopfhörer
+ Ordner
+ Stecknadel
+
diff --git a/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml b/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml
deleted file mode 100644
index f457e30ed0..0000000000
--- a/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- Spanner
- Aeroplane
-
diff --git a/matrix-sdk-android/src/main/res/values-eo/strings.xml b/matrix-sdk-android/src/main/res/values-eo/strings.xml
index 4a1e2c4c65..69b009ca7e 100644
--- a/matrix-sdk-android/src/main/res/values-eo/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-eo/strings.xml
@@ -72,72 +72,6 @@
Malplena ĉambro
-
- Hundo
- Kato
- Leono
- Ĉevalo
- Unukorno
- Porko
- Elefanto
- Kuniklo
- Pando
- Koko
- Pingveno
- Testudo
- Fiŝo
- Polpo
- Papilio
- Floro
- Arbo
- Kakto
- Fungo
- Globo
- Luno
- Nubo
- Fajro
- Banano
- Pomo
- Frago
- Maizo
- Pico
- Kuko
- Koro
- Mieneto
- Roboto
- Ĉapelo
- Okulvitroj
- Boltilo
- Kristnaska viro
- Dikfingro supren
- Ombrelo
- Sablohorloĝo
- Horloĝo
- Donaco
- Lampo
- Libro
- Grifelo
- Paperkuntenilo
- Tondilo
- Seruro
- Ŝlosilo
- Martelo
- Telefono
- Flago
- Vagonaro
- Biciklo
- Aviadilo
- Raketo
- Trofeo
- Pilko
- Gitaro
- Trumpeto
- Sonorilo
- Ankro
- Kapaŭdilo
- Dosierujo
- Pinglo
-
Komenca spegulado:
\nEnportante konton…Komenca spegulado:
diff --git a/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml b/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml
new file mode 100644
index 0000000000..16f762e362
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hundo
+ Kato
+ Leono
+ Ĉevalo
+ Unukorno
+ Porko
+ Elefanto
+ Kuniklo
+ Pando
+ Virkoko
+ Pingveno
+ Testudo
+ Fiŝo
+ Polpo
+ Papilio
+ Floro
+ Arbo
+ Kakto
+ Fungo
+ Globo
+ Luno
+ Nubo
+ Fajro
+ Banano
+ Pomo
+ Frago
+ Maizo
+ Pico
+ Torto
+ Koro
+ Rideto
+ Roboto
+ Ĉapelo
+ Okulvitroj
+ Ŝraŭbŝlosilo
+ Kristnaska viro
+ Dikfingro supren
+ Ombrelo
+ Sablohorloĝo
+ Horloĝo
+ Donaco
+ Lampo
+ Libro
+ Krajono
+ Paperkuntenilo
+ Tondilo
+ Seruro
+ Ŝlosilo
+ Martelo
+ Telefono
+ Flago
+ Vagonaro
+ Biciklo
+ Aviadilo
+ Raketo
+ Trofeo
+ Pilko
+ Gitaro
+ Trumpeto
+ Sonorilo
+ Ankro
+ Kapaŭdilo
+ Dosierujo
+ Pinglo
+
diff --git a/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml b/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
index 35b7bfc829..a8e8477005 100644
--- a/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
@@ -89,8 +89,4 @@
Mensaje eliminado por %1$sMensaje eliminado [motivo: %1$s]Mensaje eliminado por %1$s [motivo: %2$s]
- Perro
- Gato
- León
- Caballo
diff --git a/matrix-sdk-android/src/main/res/values-es/strings.xml b/matrix-sdk-android/src/main/res/values-es/strings.xml
index 3c019b3b80..ae1f5633bf 100644
--- a/matrix-sdk-android/src/main/res/values-es/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-es/strings.xml
@@ -90,65 +90,6 @@
Mensaje eliminado [motivo: %1$s]Mensaje eliminado por %1$s [motivo: %2$s]%1$s ha revocado la invitación a unirse a la sala para %2$s
- Perro
- Gato
- León
- Caballo
- Unicornio
- Cerdo
- Elefante
- Conejo
- Panda
- Gallo
- Pingüino
- Tortuga
- Pez
- Pulpo
- Mariposa
- Flor
- Árbol
- Cactus
- Seta
- Luna
- Nube
- Fuego
- Plátano
- Manzana
- Fresa
- Maíz
- Pizza
- Pastel
- Corazón
- Sombrero
- Gafas
- Llave inglesa
- Pulgares arriba
- Paraguas
- Reloj de arena
- Reloj
- Regalo
- Bombilla
- Libro
- Lápiz
- Clip
- Tijeras
- Candado
- Llave
- Martillo
- Teléfono
- Bandera
- Tren
- Bicicleta
- Avión
- Cohete
- Trofeo
- Pelota
- Guitarra
- Trompeta
- Campana
- Ancla
- Auriculares
- CarpetaSincronización Inicial
\nImportando cuenta…Sincronización Inicial:
@@ -173,12 +114,6 @@
%s ha actualizado la sala.
- Globo Terráqueo
- Cara sonriente
- Robot
- Papá Noel
- Pin
-
Sincronización Inicial:
\nImportando criptografíaSincronización Inicial:
diff --git a/matrix-sdk-android/src/main/res/values-es/strings_sas.xml b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml
new file mode 100644
index 0000000000..fd396c1778
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml
@@ -0,0 +1,53 @@
+
+
+
+ Perro
+ Gato
+ León
+ Caballo
+ Unicornio
+ Cerdo
+ Elefante
+ Conejo
+ Panda
+ Gallo
+ Pingüino
+ Tortuga
+ Pez
+ Pulpo
+ Mariposa
+ Flor
+ Árbol
+ Cactus
+ Seta
+ Globo
+ Luna
+ Nube
+ Fuego
+ Plátano
+ Manzana
+ Fresa
+ Maíz
+ Pizza
+ Tarta
+ Corazón
+ Emoticono
+ Robot
+ Sombrero
+ Gafas
+ Llave inglesa
+ Reloj
+ Regalo
+ Libro
+ Lápiz
+ Llave
+ Martillo
+ Telefono
+ Tren
+ Bicicleta
+ Bola
+ Guitarra
+ Trompeta
+ Campana
+ Alfiler
+
diff --git a/matrix-sdk-android/src/main/res/values-et/strings.xml b/matrix-sdk-android/src/main/res/values-et/strings.xml
index b7cd202063..2fbe263464 100644
--- a/matrix-sdk-android/src/main/res/values-et/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-et/strings.xml
@@ -77,72 +77,6 @@
Tühi jututuba
-
- Koer
- Kass
- Lõvi
- Hobune
- Ükssarvik
- Siga
- Elevant
- Jänes
- Panda
- Kukk
- Pingviin
- Kilpkonn
- Kala
- Kaheksajalg
- Liblikas
- Lill
- Puu
- Kaktus
- Seen
- Maakera
- Kuu
- Pilv
- Tuli
- Banaan
- Õun
- Maasikas
- Mais
- Pitsa
- Kook
- Süda
- Smaili
- Robot
- Kübar
- Prillid
- Mutrivõti
- Jõuluvana
- Pöidlad püsti
- Vihmavari
- Liivakell
- Kell
- Kingitus
- Lambipirn
- Raamat
- Pliiats
- Kirjaklamber
- Käärid
- Lukk
- Võti
- Haamer
- Telefon
- Lipp
- Rong
- Jalgratas
- Lennuk
- Rakett
- Auhind
- Pall
- Kitarr
- Trompet
- Kelluke
- Ankur
- Kõrvaklapid
- Kaust
- Nööpnõel
-
Alglaadimine:
\nImpordin kontot…Alglaadimine:
@@ -295,8 +229,4 @@
Sa lülitasid sisse läbiva krüptimise.Sa lülitasid sisse läbiva krüptimise (kasutusel on tundmatu algoritm %1$s).
- Võta vastu
- Keeldu
- Lõpeta kõne
-
diff --git a/matrix-sdk-android/src/main/res/values-et/strings_sas.xml b/matrix-sdk-android/src/main/res/values-et/strings_sas.xml
new file mode 100644
index 0000000000..60df725eaa
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-et/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Koer
+ Kass
+ Lõvi
+ Hobune
+ Ükssarvik
+ Siga
+ Elevant
+ Jänes
+ Panda
+ Kukk
+ Pingviin
+ Kilpkonn
+ Kala
+ Kaheksajalg
+ Liblikas
+ Lill
+ Puu
+ Kaktus
+ Seen
+ Maakera
+ Kuu
+ Pilv
+ Tuli
+ Banaan
+ Õun
+ Maasikas
+ Mais
+ Pitsa
+ Kook
+ Süda
+ Smaili
+ Robot
+ Kübar
+ Prillid
+ Mutrivõti
+ Jõuluvana
+ Pöidlad püsti
+ Vihmavari
+ Liivakell
+ Kell
+ Kingitus
+ Lambipirn
+ Raamat
+ Pliiats
+ Kirjaklamber
+ Käärid
+ Lukk
+ Võti
+ Haamer
+ Telefon
+ Lipp
+ Rong
+ Jalgratas
+ Lennuk
+ Rakett
+ Auhind
+ Pall
+ Kitarr
+ Trompet
+ Kelluke
+ Ankur
+ Kõrvaklapid
+ Kaust
+ Nööpnõel
+
diff --git a/matrix-sdk-android/src/main/res/values-eu/strings.xml b/matrix-sdk-android/src/main/res/values-eu/strings.xml
index 1a5c81fe5e..bc61035c24 100644
--- a/matrix-sdk-android/src/main/res/values-eu/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-eu/strings.xml
@@ -78,70 +78,6 @@
%1$s erabiltzaileak mezua kendu duMezua kendu da [arrazoia: %1$s]%1$s erabiltzaileak mezua kendu du [arrazoia: %2$s]
- Txakurra
- Katua
- Lehoia
- Zaldia
- Unikornioa
- Zerria
- Elefantea
- Untxia
- Panda
- Oilarra
- Pinguinoa
- Dortoka
- Arraina
- Olagarroa
- Tximeleta
- Lorea
- Zuhaitza
- Kaktusa
- Perretxikoa
- Lurra
- Ilargia
- Hodeia
- Sua
- Banana
- Sagarra
- Marrubia
- Artoa
- Pizza
- Pastela
- Bihotza
- Irrifartxoa
- Robota
- Txanoa
- Betaurrekoak
- Giltza
- Santa
- Ederto
- Aterkia
- Harea-erlojua
- Erlojua
- Oparia
- Bonbilla
- Liburua
- Arkatza
- Klipa
- Artaziak
- Giltzarrapoa
- Giltza
- Mailua
- Telefonoa
- Bandera
- Trena
- Bizikleta
- Hegazkina
- Kohetea
- Saria
- Baloia
- Gitarra
- Tronpeta
- Kanpaia
- Aingura
- Aurikularrak
- Karpeta
- TxintxetaHasierako sinkronizazioa:
\nKontua inportatzen…
diff --git a/matrix-sdk-android/src/main/res/values-fa/strings.xml b/matrix-sdk-android/src/main/res/values-fa/strings.xml
index 18d8578e54..b88a98459d 100644
--- a/matrix-sdk-android/src/main/res/values-fa/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fa/strings.xml
@@ -77,72 +77,6 @@
اتاق خالی
-
- سگ
- گربه
- شیر
- اسب
- تکشاخ
- خوک
- فیل
- خرگوش
- پاندا
- خروس
- پنگوئن
- لاکپشت
- ماهی
- هشتپا
- پروانه
- گل
- درخت
- کاکتوس
- قارچ
- جهان
- ماه
- ابر
- آتش
- موز
- سیب
- توتفرنگی
- بلال
- پیتزا
- کیک
- قلب
- لبخند
- آدمآهنی
- کلاه
- عینک
- آچار
- بابانوئل
- شست
- چتر
- ساعت شنی
- ساعت
- هدیه
- لامپ
- کتاب
- مداد
- گیره کاغذ
- قیچی
- قفل
- کلید
- چکّش
- تلفن
- پرچم
- قطار
- دوچرخه
- هواپیما
- موشک
- جام
- توپ
- گیتار
- ترومپت
- زنگ
- لنگر
- هدفون
- پوشه
- پونز
-
همگامسازی نخستین:
\nدر حال درونریزی حساب…همگامسازی نخستین:
diff --git a/matrix-sdk-android/src/main/res/values-fi/strings.xml b/matrix-sdk-android/src/main/res/values-fi/strings.xml
index 078769942c..fccd22d3b6 100644
--- a/matrix-sdk-android/src/main/res/values-fi/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fi/strings.xml
@@ -79,70 +79,6 @@
%1$s poisti viestinViesti poistettu [syy: %1$s]%1$s poisti viestin [syy: %2$s]
- Koira
- Kissa
- Leijona
- Hevonen
- Yksisarvinen
- Sika
- Norsu
- Kani
- Panda
- Kukko
- Pingviini
- Kilpikonna
- Kala
- Tursas
- Perhonen
- Kukka
- Puu
- Kaktus
- Sieni
- Maapallo
- Kuu
- Pilvi
- Tuli
- Banaani
- Omena
- Mansikka
- Maissi
- Pizza
- Kakku
- Sydän
- Hymiö
- Robotti
- Hattu
- Silmälasit
- Jakoavain
- Joulupukki
- Peukut ylös
- Sateenvarjo
- Tiimalasi
- Kello
- Lahja
- Hehkulamppu
- Kirja
- Lyijykynä
- Klemmari
- Sakset
- Lukko
- Avain
- Vasara
- Puhelin
- Lippu
- Juna
- Polkupyörä
- Lentokone
- Raketti
- Palkinto
- Pallo
- Kitara
- Trumpetti
- Soittokello
- Ankkuri
- Kuulokkeet
- Kansio
- NuppineulaAlkusynkronointi:
\nTuodaan tiliä…
diff --git a/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml b/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml
new file mode 100644
index 0000000000..b690fee4ed
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Koira
+ Kissa
+ Leijona
+ Hevonen
+ Yksisarvinen
+ Sika
+ Norsu
+ Kani
+ Panda
+ Kukko
+ Pingviini
+ Kilpikonna
+ Kala
+ Tursas
+ Perhonen
+ Kukka
+ Puu
+ Kaktus
+ Sieni
+ Maapallo
+ Kuu
+ Pilvi
+ Tuli
+ Banaani
+ Omena
+ Mansikka
+ Maissi
+ Pizza
+ Kakku
+ Sydän
+ Hymynaama
+ Robotti
+ Hattu
+ Silmälasit
+ Mutteriavain
+ Joulupukki
+ Peukalo ylös
+ Sateenvarjo
+ Tiimalasi
+ Pöytäkello
+ Lahja
+ Hehkulamppu
+ Kirja
+ Lyijykynä
+ Paperiliitin
+ Sakset
+ Lukko
+ Avain
+ Vasara
+ Puhelin
+ Lippu
+ Juna
+ Polkupyörä
+ Lentokone
+ Raketti
+ Palkinto
+ Pallo
+ Kitara
+ Trumpetti
+ Soittokello
+ Ankkuri
+ Kuulokkeet
+ Kansio
+ Nuppineula
+
diff --git a/matrix-sdk-android/src/main/res/values-fr/strings.xml b/matrix-sdk-android/src/main/res/values-fr/strings.xml
index aad3bd1afb..71b956a7e7 100644
--- a/matrix-sdk-android/src/main/res/values-fr/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fr/strings.xml
@@ -78,70 +78,6 @@
Message supprimé par %1$sMessage supprimé [motif : %1$s]Message supprimé par %1$s [motif : %2$s]
- Chien
- Chat
- Lion
- Cheval
- Licorne
- Cochon
- Éléphant
- Lapin
- Panda
- Coq
- Manchot
- Tortue
- Poisson
- Pieuvre
- Papillon
- Fleur
- Arbre
- Cactus
- Champignon
- Terre
- Lune
- Nuage
- Feu
- Banane
- Pomme
- Fraise
- Maïs
- Pizza
- Gâteau
- Cœur
- Smiley
- Robot
- Chapeau
- Lunettes
- Clé plate
- Père Noël
- Pouce levé
- Parapluie
- Sablier
- Horloge
- Cadeau
- Ampoule
- Livre
- Crayon
- Trombone
- Ciseaux
- Cadenas
- Clé
- Marteau
- Téléphone
- Drapeau
- Train
- Vélo
- Avion
- Fusée
- Trophée
- Balle
- Guitare
- Trompette
- Cloche
- Ancre
- Écouteurs
- Dossier
- ÉpingleSynchronisation initiale :
\nImportation du compte…
diff --git a/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml b/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml
new file mode 100644
index 0000000000..af9d797542
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Chien
+ Chat
+ Lion
+ Cheval
+ Licorne
+ Cochon
+ Éléphant
+ Lapin
+ Panda
+ Coq
+ Manchot
+ Tortue
+ Poisson
+ Poulpe
+ Papillon
+ Fleur
+ Arbre
+ Cactus
+ Champignon
+ Globe
+ Lune
+ Nuage
+ Feu
+ Banane
+ Pomme
+ Fraise
+ Maïs
+ Pizza
+ Gâteau
+ Cœur
+ Sourire
+ Robot
+ Châpeau
+ Lunettes
+ Clé à molette
+ Père Noël
+ Pouce en l\'air
+ Parapluie
+ Sablier
+ Réveil
+ Cadeau
+ Ampoule
+ Livre
+ Crayon
+ Trombone
+ Ciseaux
+ Cadenas
+ Clé
+ Marteau
+ Téléphone
+ Drapeau
+ Train
+ Vélo
+ Avion
+ Fusée
+ Trophée
+ Ballon
+ Guitare
+ Trompette
+ Cloche
+ Ancre
+ Casque audio
+ Dossier
+ Punaise
+
diff --git a/matrix-sdk-android/src/main/res/values-hu/strings.xml b/matrix-sdk-android/src/main/res/values-hu/strings.xml
index 35f35eaecd..896a97b023 100644
--- a/matrix-sdk-android/src/main/res/values-hu/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-hu/strings.xml
@@ -77,70 +77,6 @@
Üzenetet eltávolította: %1$sÜzenet eltávolítva [ok: %1$s]Üzenetet eltávolította: %1$s [ok: %2$s]
- Kutya
- Macska
- Oroszlán
- Ló
- Egyszarvú
- Malac
- Elefánt
- Nyúl
- Panda
- Kakas
- Pingvin
- Teknős
- Hal
- Polip
- Pillangó
- Virág
- Fa
- Kaktusz
- Gomba
- Föld
- Hold
- Felhő
- Tűz
- Banán
- Alma
- Eper
- Kukorica
- Pizza
- Süti
- Szív
- Smiley
- Robot
- Kalap
- Szemüveg
- Csavarkulcs
- Télapó
- Hüvelykujj fel
- Esernyő
- Homokóra
- Óra
- Ajándék
- Égő
- Könyv
- Ceruza
- Gémkapocs
- Olló
- Zár
- Kulcs
- Kalapács
- Telefon
- Zászló
- Vonat
- Kerékpár
- Repülő
- Rakéta
- Trófea
- Labda
- Gitár
- Trombita
- Harang
- Vasmacska
- Fejhallgató
- Mappa
- TűInduló szinkronizáció:
\nFiók betöltése…
diff --git a/matrix-sdk-android/src/main/res/values-it/strings.xml b/matrix-sdk-android/src/main/res/values-it/strings.xml
index 2b2a097f13..cf081752a2 100644
--- a/matrix-sdk-android/src/main/res/values-it/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-it/strings.xml
@@ -78,70 +78,6 @@
Messaggio rimosso da %1$sMessaggio rimosso [motivo: %1$s]Messaggio rimosso da %1$s [motivo: %2$s]
- Cane
- Gatto
- Leone
- Cavallo
- Unicorno
- Maiale
- Elefante
- Coniglio
- Panda
- Gallo
- Pinguino
- Tartaruga
- Pesce
- Piovra
- Farfalla
- Fiore
- Albero
- Cactus
- Fungo
- Globo
- Luna
- Nuvola
- Fuoco
- Banana
- Mela
- Fragola
- Mais
- Pizza
- Torta
- Cuore
- Sorriso
- Robot
- Cappello
- Occhiali
- Chiave inglese
- Babbo Natale
- Pollice in su
- Ombrello
- Clessidra
- Orologio
- Regalo
- Lampadina
- Libro
- Matita
- Graffetta
- Forbici
- Lucchetto
- Chiave
- Martello
- Telefono
- Bandiera
- Treno
- Bicicletta
- Aeroplano
- Razzo
- Trofeo
- Palla
- Chitarra
- Tromba
- Campana
- Ancora
- Cuffie
- Cartella
- SpilloSync iniziale:
\nImportazione account…
@@ -296,8 +232,4 @@
Hai attivato la crittografia end-to-end.Hai attivato la crittografia end-to-end (algoritmo %1$s sconosciuto).
- Accetta
- Rifiuta
- Riaggancia
-
diff --git a/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml
new file mode 100644
index 0000000000..618302eb4f
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml
@@ -0,0 +1,20 @@
+
+
+
+ 犬
+ 猫
+ 馬
+ たこ
+ 花
+ 木
+ きのこ
+ 月
+ リンゴ
+ ケーキ
+ ロボと
+ めがね
+ 本
+ 電話機
+ 電車
+ 自転車
+
diff --git a/matrix-sdk-android/src/main/res/values-kab/strings.xml b/matrix-sdk-android/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..0d1cad6550
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-kab/strings.xml
@@ -0,0 +1,225 @@
+
+
+ %1$s: %2$s
+ %1$s t.yuzen tugna.
+ Tuzneḍ tugna.
+ Tinubga n %s
+ Tinubga-k•m
+ %1$s yesnulfa-d taxxamt
+ Tesnulfaḍ-d taxxamt-a
+ %1$s inced-d %2$s
+ Tnecdeḍ-d %1$s
+ %1$s inced-ik-id
+ %1$s yedda ɣer texxamt
+ Teddiḍ ɣer texxamt
+ %1$s yeǧǧa taxxamt
+ Teǧǧiḍ taxxamt
+ %1$s yugi/tugi tinubga
+ Tufiḍ tinubga
+ %1$s yessufeɣ %2$s
+ Tessufɣeḍ %1$s
+ Tbeddleḍ avatar-inek·inem
+ Anedbal
+ Aseɣyad
+ Amezwer
+ Sagen
+
+ %1$s seg %2$s ɣer %3$s
+
+ Tegguma ad d-tali tugna
+
+ Tansa n yimayl
+
+ %1$s azen astiker.
+ Tuzneḍ amenṭaḍ.
+
+ %1$s yekkes agdal i %2$s
+ Tekkseḍ agdal i %1$s
+ %1$s igdel %2$s
+ Tgedleḍ %1$s
+ %1$s issefsex tinubga n %2$s
+ Tesfesxeḍ tinubga n %1$s
+ %1$s ibeddel avatar-is
+ %1$s isbadu isem-is i d-ittuseknen ɣer %2$s
+ Tesbaduḍ isem-ik•im i d-ittuseknen ɣer %1$s
+ %1$s ibeddel isem-is i d-ittuseknen seg %2$s ɣer %3$s
+ Tbeddleḍ isem-ik•im i d-ittuseknen seg %1$s ɣer %2$s
+ %1$s yekkes isem-is i d-ittuseknen (yella %2$s)
+ Tekkseḍ isem-ik·im yettwaskanen (d %1$s)
+ %1$S isnifel asentel s: %2$S
+ Tesnifleḍ asentel s: %2$S
+ %1$s ibeddel avaṭar n texxamt
+ Tbeddleḍ avaṭar n texxamt
+ %1$s ibeddel isem n texxamt s: %2$s
+ Tbeddleḍ isem n texxamt s: %2$s
+ %s isɛedda siwel s tvidyut.
+ Tesɛeddaḍ siwel s tvidyut.
+ %s isɛedda asiwel s taɣect.
+ Tesɛeddaḍ siwel s taɣect.
+ %s yuzen isefka i usbadu n usiwel.
+ Tuzneḍ isefka i usbadu n usiwel.
+ %s yerra ɣef usiwel.
+ Terriḍ ɣef usiwel.
+ %s iḥbes asiwel.
+ Tḥebseḍ asiwel.
+ meṛṛa iɛeggalen n texxamt, segmi ara d-ttwanecden.
+ meṛṛa iɛeggalen n texamt, segmi ara d-rnun.
+ meṛṛa iɛeggalen n texxamt.
+ yal yiwen.
+ arussin (%s).
+ %1$s isermed awgelhen seg yixef ɣer yixef (%2$s)
+ Tesremdeḍ awgelhen seg yixef ɣer yixef (%2$s)
+ %s ileqqem taxxamt-a.
+ Tleqqmeḍ taxxamt-a.
+
+ %1$s isuter-d asarag VoIP
+ Tsutreḍ-d asarag VoIP
+ Asarag VoIP yebda
+ Asarag VoIP yekfa
+
+ (avatar daɣen ibeddel)
+ %1$s yekkes isem n texxamt
+ Tekkseḍ isem n texxamt
+ %1$s yekkes asentel n texxamt
+ Tekkseḍ asentel n texxamt
+ %1$s yekkes avatar n texxamt
+ Tekkseḍ avatar n texxamt
+ Izen ittwakkes
+ Izen ittwakkes sɣur %1$s
+ Izen ittwakkes [tamentilt: %1$s]
+ Izen ittwakkes sɣur %1$s [tamentilt: %2$s]
+ %1$s ileqqem amaɣnu-ines %2$s
+ Tleqqmeḍ amaɣnu-inek•inem %1$s
+ %1$s yuzen tinubga i %2$s akken ad yeddu ɣer texxamt
+ Tuzneḍ tinubga i %1$s akken ad yeddu ɣer texxamt
+ %1$s iqbel tinubga i %2$s
+ Tqebleḍ tinubga i %1$s
+
+ %1$s yerna awiǧit %2$s
+ Terniḍ awiǧit %1$s
+ %1$s yekkes awiǧit %2$s
+ Tekkseḍ awiǧit %1$s
+ %1$s ibeddel awiǧit %2$s
+ Tbeddleḍ awiǧit %1$s
+
+ Sagen (%1$)
+ Tbeddleḍ aswir n tezmert n %1$s.
+ %1$s ibeddel aswir n tezmert n %2$s.
+ ** Awgelhen d awezɣi: %s **
+ Ibenk n umazan ur aɣ-d-yuzin ara tisura i yizen-a.
+
+ Tuzna n yizen d tawezɣit
+
+ Tuccḍa deg uẓeṭṭa
+ Tuccḍa deg Matrix
+
+ %1$s iga amazray n texxamyt i d-iteddun yettban i %2$s
+ Tgiḍ amazray n texxamyt i d-iteddun yettban i %1$s
+ %1$s issefsax tinubga i %2$s i wakken ad d-yekcem ɣer texxamt
+ Tesfesxeḍ tinubga i %1$s i wakken ad d-yernu ɣer texxamt
+ D awezɣi tura ad nales ad nuɣal ɣer texxamt tilemt.
+
+ Izen yettwawgelhen
+
+ Uṭṭun n tiliɣri
+
+ Tinubga sɣur %s
+ Tinubga ɣer texxamt
+
+ %1$s d %2$s
+
+
+ %1$s d 1 wayeḍ
+ %1$s d %2$d wiyaḍ
+
+
+ Tremdeḍ awgelhen seg yixef ɣer yixef (alguritm %1$s ur yettwassen ara).
+
+ %s isuter-d ad isenqed tasarut-ik·im, maca amsaɣ-ik·im ur issefrak ara asenqed n tsura deg yidiwenniyen. Ilaq-ak·am useqdec asenqed iqdim n tsura i usenqed n tsura.
+
+ Taxxamt tilemt
+
+ Amtawi n tazwara:
+\nAktar n umiḍan…
+ Amtawi n tazwara:
+\nAktar n uwgelhen
+ Amtawi n tazwara:
+\nAktar n texxamin
+ Amtawi n tazwara:
+\nAktar n texxamin iɣer terniḍ
+ Amtawi n tazwara:
+\nAktar n texxamin iɣer tettwanecdeḍ
+ Amtawi n tazwara:
+\nAktar n texxamin i teǧǧiḍ
+ Amtawi n tazwara:
+\nAktar n tmezdagnutin
+ Amtawi n tazwara:
+\nAktar n yisefka n umiḍan
+
+ Tuzzna n yizen…
+ Tinubga n %1$s. Tamentilt: %2$s
+ Tinubga-k•m. Tamentilt: %1$s
+ %1$s inced %2$s. Tamentilt: %3$s
+ Tnecdeḍ %1$s. Tamentilt: %2$s
+ %1$s inced-ik•ikem. Tamentilt: %2$s
+ %1$s yedda ɣer texxamt. Tamentilt: %2$s
+ Teddiḍ ɣer texxamt. Tamentilt: %1$s
+ %1$s yeǧǧa taxxamt. Tamentilt: %2$s
+ Teǧǧiḍ taxxamt. Tamentilt: %1$s
+ %1$s yugi tinubga. Tamentilt: %2$s
+ Tugiḍ tinubga. Tamentilt: %1$s
+ %1$s yessufeɣ %2$s. Tamentilt: %3$s
+ Tessufɣeḍ %1$s. Tamentilt: %2$s
+ %1$s yekkes agdal i %2$s. Tamentilt: %3$s
+ Tekkseḍ agdal i %1$s. Tamentilt: %2$s
+ %1$s igdel %2$s. Tamentilt: %3$s
+ Tgedleḍ %1$s. Tamentilt: %2$s
+ %1$s yuzen tinubga i %2$s akken ad yeddu ɣer texxamt. Tamentilt: %3$s
+ Tuzneḍ tinubga i %1$s iwakken ad yeddu ɣer texxamt. Tamentilt: %2$s
+ %1$s iqbel tinubga i %2$s. Tamentilt: %3$s
+ Tqebleḍ tinubga i %1$s. Tamentilt: %2$s
+ %1$s issefsex tinubga n %2$s. Tamentilt: %3$s
+ Tesfesxeḍ tinubga n %1$s. Tamentilt: %2$s
+
+
+ %1$s yerna %2$s d tansa i texxamt-a.
+ %1$s yerna %2$s d tansiwin i texxamt-a.
+
+
+
+ Terniḍ %1$s d tansa i texxamt-a.
+ Terniḍ %1$s d tansiwin i texxamt-a.
+
+
+
+ %1$s yekkes %2$s am tansa i texxamt-a.
+ %1$s yekkes %3$s am tansiwin i texxamt-a.
+
+
+
+ Tekkseḍ %1$s am tansa i texxamt-a.
+ Tekkseḍ %2$s am tansiwin i texxamt-a.
+
+
+ %1$s yerna %2$s terniḍ tekkseḍ %3s am tansiwin i texxamt-a.
+ Terniḍ %1$s terniḍ tekkseḍ %2$s am tansiwin i texxamt-a.
+
+ %1$s isbadu %2$s am tansa tagejdant i texxamt-a.
+ Tesbaduḍ %1$s am tansa tagejdant i texxamt-a.
+ %1$s yekkes tansa tagejdant i texxamt-a.
+ Tekkseḍ tansa tagejdant i texxamt-a.
+
+ %1$s isireg inebgawen ad ddun ɣer texxamt.
+ Tsirgeḍ inebgawen ad ddun ɣer texxamt.
+ %1$s issewḥel inebgawen iwakken ur tteddun ara ɣer texxamt.
+ Tesweḥleḍ inebgawen iwakken ur tteddun ara ɣer texxamt.
+
+ %1$s yermed awgelhen seg yixef ɣer yixef.
+ Tremdeḍ awgelhen seg yixef ɣer yixef.
+ %1$s yermed awgelhen seg yixef ɣer yixef (alguritm %2$s ur yettwassen ara).
+ Sfeḍ tabdart n uraǧu n tuzzna
+
+ %1$s issefsex tinubga n %2$s i tmerniwt ɣer texxamt. Tamentilt: %2$s
+ Tesfesxeḍ tinubga n %1$s i tmerna ɣer texxamt. Tamentilt: %2$s
+ Yegguma ad yaru
+
diff --git a/matrix-sdk-android/src/main/res/values-ko/strings.xml b/matrix-sdk-android/src/main/res/values-ko/strings.xml
index 88c5e7d618..eee67628eb 100644
--- a/matrix-sdk-android/src/main/res/values-ko/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-ko/strings.xml
@@ -2,7 +2,6 @@
%1$s: %2$s%s님의 초대
- 헤드폰%1$s님이 사진을 보냈습니다.%1$s님이 스티커를 보냈습니다.
@@ -78,71 +77,6 @@
빈 방
-
- 개
- 고양이
- 사자
- 말
- 유니콘
- 돼지
- 코끼리
- 토끼
- 판다
- 수탉
- 펭귄
- 거북
- 물고기
- 문어
- 나비
- 꽃
- 나무
- 선인장
- 버섯
- 지구본
- 달
- 구름
- 불
- 바나나
- 사과
- 딸기
- 옥수수
- 피자
- 케이크
- 하트
- 웃음
- 로봇
- 모자
- 안경
- 스패너
- 산타클로스
- 좋아요
- 우산
- 모래시계
- 시계
- 선물
- 전구
- 책
- 연필
- 클립
- 가위
- 자물쇠
- 열쇠
- 망치
- 전화기
- 깃발
- 기차
- 자전거
- 비행기
- 로켓
- 트로피
- 공
- 기타
- 트럼펫
- 종
- 닻
- 폴더
- 핀
-
초기 동기화:
\n계정 가져오는 중…초기 동기화:
diff --git a/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml b/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml
new file mode 100644
index 0000000000..c348b5bfbb
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katt
+ Løve
+ Hest
+ Enhjørning
+ Gris
+ Elefant
+ Kanin
+ Panda
+ Hane
+ Pingvin
+ Skilpadde
+ Fisk
+ Blekksprut
+ Sommerfugl
+ Blomst
+ Tre
+ Kaktus
+ Sopp
+ Globus
+ Måne
+ Sky
+ Flamme
+ Banan
+ Eple
+ Jordbær
+ Mais
+ Pizza
+ Kake
+ Hjerte
+ Smilefjes
+ Robot
+ Hatt
+ Briller
+ Fastnøkkel
+ Julenisse
+ Tommel Opp
+ Paraply
+ Timeglass
+ Klokke
+ Gave
+ Lyspære
+ Bok
+ Blyant
+ BInders
+ Saks
+ Lås
+ Nøkkel
+ Hammer
+ Telefon
+ Flagg
+ Tog
+ Sykkel
+ Fly
+ Rakett
+ Pokal
+ Ball
+ Gitar
+ Trompet
+ Bjelle
+ Anker
+ Hodetelefoner
+ Mappe
+ Tegnestift
+
diff --git a/matrix-sdk-android/src/main/res/values-nl/strings.xml b/matrix-sdk-android/src/main/res/values-nl/strings.xml
index 22eb61f109..1b05052ba6 100644
--- a/matrix-sdk-android/src/main/res/values-nl/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-nl/strings.xml
@@ -87,70 +87,6 @@
Bericht verwijderd door %1$sBericht verwijderd [reden: %1$s]Bericht verwijderd door %1$s [reden: %2$s]
- Hond
- Kat
- Leeuw
- Paard
- Eenhoorn
- Varken
- Olifant
- Konijn
- Panda
- Haan
- Pinguïn
- Schildpad
- Vis
- Octopus
- Vlinder
- Bloem
- Boom
- Cactus
- Paddenstoel
- Aardbol
- Maan
- Wolk
- Vuur
- Banaan
- Appel
- Aardbei
- Maïs
- Pizza
- Taart
- Hart
- Smiley
- Robot
- Hoed
- Bril
- Moersleutel
- Kerstman
- Duim omhoog
- Paraplu
- Zandloper
- Klok
- Cadeau
- Gloeilamp
- Boek
- Potlood
- Paperclip
- Schaar
- Slot
- Sleutel
- Hamer
- Telefoon
- Vlag
- Trein
- Fiets
- Vliegtuig
- Raket
- Trofee
- Bal
- Gitaar
- Trompet
- Bel
- Anker
- Koptelefoon
- Map
- SpeldInitiële synchronisatie:
\nAccount wordt geïmporteerd…
diff --git a/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml b/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml
new file mode 100644
index 0000000000..077244232a
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hond
+ Kat
+ Leeuw
+ Paard
+ Eenhoorn
+ Varken
+ Olifant
+ Konijn
+ Panda
+ Haan
+ Pinguïn
+ Schildpad
+ Vis
+ Octopus
+ Vlinder
+ Bloem
+ Boom
+ Cactus
+ Paddenstoel
+ Wereldbol
+ Maan
+ Wolk
+ Vuur
+ Banaan
+ Appel
+ Aardbei
+ Maïs
+ Pizza
+ Taart
+ Hart
+ Smiley
+ Robot
+ Hoed
+ Bril
+ Moersleutel
+ Kerstman
+ Duim omhoog
+ Paraplu
+ Zandloper
+ Wekker
+ Geschenk
+ Gloeilamp
+ Boek
+ Potlood
+ Papierklemmetje
+ Schaar
+ Slot
+ Sleutel
+ Hamer
+ Telefoon
+ Vlag
+ Trein
+ Fiets
+ Vliegtuig
+ Raket
+ Trofee
+ Bal
+ Gitaar
+ Trompet
+ Bel
+ Anker
+ Koptelefoon
+ Map
+ Duimspijker
+
diff --git a/matrix-sdk-android/src/main/res/values-nn/strings.xml b/matrix-sdk-android/src/main/res/values-nn/strings.xml
index 601cf4c9df..d986e697ad 100644
--- a/matrix-sdk-android/src/main/res/values-nn/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-nn/strings.xml
@@ -77,70 +77,6 @@
%1$s strauk meldingiMeldingi vart stroki [av di: %1$s]%1$s strauk meldingi [av di: %2$s]
- Hund
- Katt
- Løva
- Hest
- Einhyrning
- Gris
- Elefant
- Hare
- Panda
- Hane
- Pingvin
- Skjoldpadda
- Fisk
- Blekksprut
- Fivrelde
- Blome
- Tre
- Kaktus
- Sopp
- Klote
- Måne
- Sky
- Eld
- Banan
- Eple
- Jordbær
- Mais
- Pizza
- Kaka
- Hjarta
- Smilandlit
- Robot
- Hatt
- Brillor
- Skiftenykel
- Nissen
- Tumalen Upp
- Regnskjold
- Timeglas
- Ur
- Gåva
- Ljospera
- Bok
- Blyant
- Binders
- Saks
- Lås
- Nykel
- Hamar
- Telefon
- Flagg
- Tog
- Sykkel
- Flyg
- Rakett
- Pokal
- Ball
- Gitar
- Trompet
- Klokka
- Ankar
- Hodetelefon
- Mappa
- Nål%s oppgraderte rommet.
diff --git a/matrix-sdk-android/src/main/res/values-pl/strings.xml b/matrix-sdk-android/src/main/res/values-pl/strings.xml
index dc380516b7..0d79edc658 100644
--- a/matrix-sdk-android/src/main/res/values-pl/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-pl/strings.xml
@@ -79,73 +79,8 @@
Wiadomość usunięta przez %1$sWiadomość usunięta [powód: %1$s]Wiadomość usunięta przez %1$s [powód: %2$s]
- Pies
- Kot
- Lew
- Koń
- Jednorożec
- Świnia
- Słoń
- Królik
- Panda
- Kogut
- Pingwin
- Żółw
- Ryba
- Ośmiornica
- Motyl
- Kwiat
- Drzewo
- Kaktus
- Grzyb
- Księżyc
- Chmura
- Ogień
- Banan
- Jabłko
- Truskawka
- Kukurydza
- Pizza
- Ciasto
- Serce
- Robot
- Kapelusz
- Okulary
- Parasol
- Klepsydra
- Zegar
- Żarówka
- Książka
- Ołówek
- Spinacz
- Nożyczki
- Klucz
- Telefon
- Flaga
- Pociąg
- Rower
- Samolot
- Rakieta
- Trofeum
- Gitara
- Trąbka
- Dzwonek
- Kotwica
- Słuchawki
- Folder
- Pinezka
-
- Ziemia
- Uśmiech
- Klucz francuski
- Mikołaj
- Prezent
- Młotek%s zakutalizował(a) ten pokój.
- Kciuk w górę
- Zamek
- PiłkaSynchronizacja początkowa:
\nImportowanie konta…Synchronizacja początkowa:
diff --git a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
index e1b99506c8..2ba369b93a 100644
--- a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
@@ -25,9 +25,9 @@
%s aceitou a chamada.%s encerrou a chamada.%1$s deixou o histórico futuro da sala visível para %2$s
- todos os membros da sala, a partir do momento em que foram convidados.
- todos os membros da sala, a partir do momento em que entraram nela.
- todos os membros da sala.
+ todos os participantes da sala, a partir do momento em que foram convidados.
+ todos os participantes da sala, a partir do momento em que entraram nela.
+ todos os participantes da sala.qualquer pessoa.desconhecido (%s).%1$s ativou a criptografia de ponta a ponta (%2$s)
@@ -124,10 +124,10 @@
Você removeu a descrição da sala%1$s removeu a foto da salaVocê removeu a foto da sala
- Mensagem removida
- Mensagem removida por %1$s
- Mensagem removida [motivo: %1$s]
- Mensagem removida por %1$s [motivo: %2$s]
+ Mensagem apagada
+ Mensagem apagada por %1$s
+ Mensagem apagada [motivo: %1$s]
+ Mensagem apagada por %1$s [motivo: %2$s]Você atualizou o seu perfil %1$sVocê enviou um convite para %1$s entrar na sala%1$s cancelou o convite a %2$s para entrar na sala
@@ -151,71 +151,6 @@
%1$s alterou o nível de permissão de %2$s.%1$s de %2$s para %3$s
- Cachorro
- Gato
- Leão
- Cavalo
- Unicórnio
- Porco
- Elefante
- Coelho
- Panda
- Galo
- Pinguim
- Tartaruga
- Peixe
- Polvo
- Borboleta
- Flor
- Árvore
- Cacto
- Cogumelo
- Globo
- Lua
- Nuvem
- Fogo
- Banana
- Maçã
- Morango
- Milho
- Pizza
- Bolo
- Coração
- Sorriso
- Robô
- Chapéu
- Óculos
- Chave inglesa
- Papai-noel
- Joinha
- Guarda-chuva
- Ampulheta
- Relógio
- Presente
- Lâmpada
- Livro
- Lápis
- Clipe de papel
- Tesoura
- Cadeado
- Chave
- Martelo
- Telefone
- Bandeira
- Trem
- Bicicleta
- Avião
- Foguete
- Troféu
- Bola
- Guitarra
- Trombeta
- Sino
- Âncora
- Fones de ouvido
- Pasta
- Alfinete
-
Primeira sincronização:↵
\nImportando a conta…Primeira sincronização:↵
@@ -302,8 +237,4 @@
%s deseja confirmar a sua chave, mas o seu aplicativo não suporta a confirmação da chave da conversa. Você precisará usar a confirmação tradicional de chaves para confirmar chaves.
- Aceitar
- Recusar
- Encerrar
-
diff --git a/matrix-sdk-android/src/main/res/values-ru/strings.xml b/matrix-sdk-android/src/main/res/values-ru/strings.xml
index 1657d80f1c..a4d752782e 100644
--- a/matrix-sdk-android/src/main/res/values-ru/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-ru/strings.xml
@@ -91,70 +91,6 @@
%1$s удалил(а) сообщениеСообщение удалено [причина: %1$s]%1$s удалил(а) сообщение [причина: %2$s]
- Собака
- Кошка
- Лев
- Лошадь
- Единорог
- Поросёнок
- Слон
- Кролик
- Панда
- Петух
- Пингвин
- Черепаха
- Рыба
- Осьминог
- Бабочка
- Цветок
- Дерево
- Кактус
- Гриб
- Земля
- Луна
- Облако
- Огонь
- Банан
- Яблоко
- Клубника
- Кукуруза
- Пицца
- Пирожное
- Сердце
- Смайлик
- Робот
- Шляпа
- Очки
- Гаечный ключ
- Санта
- Большой палец вверх
- Зонтик
- Песочные часы
- Часы
- Подарок
- Лампочка
- Книга
- Карандаш
- Скрепка для бумаг
- Ножницы
- Замок
- Ключ
- Молоток
- Телефон
- Флаг
- Поезд
- Велосипед
- Самолёт
- Ракета
- Трофей
- Мяч
- Гитара
- Труба
- Колокол
- Якорь
- Наушники
- Папка
- БулавкаНачальная синхронизация:
\nИмпорт учетной записи…
@@ -313,8 +249,5 @@
Вы отправили данные для начала звонка.%1$s удалил(а) аватар комнатыВы удалили аватар комнаты
- Принять
- Отклонить
- Завершить звонок
diff --git a/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml
new file mode 100644
index 0000000000..f60d7026b6
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Собака
+ Кошка
+ Лев
+ Лошадь
+ Единорог
+ Свинья
+ Слон
+ Кролик
+ Панда
+ Петух
+ Пингвин
+ Черепаха
+ Рыба
+ Осьминог
+ Бабочка
+ Цветок
+ Дерево
+ Кактус
+ Гриб
+ Глобус
+ Луна
+ Облако
+ Огонь
+ Банан
+ Яблоко
+ Клубника
+ Кукуруза
+ Пицца
+ Торт
+ Сердце
+ Улыбка
+ Робот
+ Шляпа
+ Очки
+ Ключ
+ Санта
+ Большой палец вверх
+ Зонт
+ Песочные часы
+ Часы
+ Подарок
+ Лампочка
+ Книга
+ Карандаш
+ Скрепка
+ Ножницы
+ Замок
+ Ключ
+ Молоток
+ Телефон
+ Флаг
+ Поезд
+ Велосипед
+ Самолет
+ Ракета
+ Кубок
+ Мяч
+ Гитара
+ Труба
+ Колокол
+ Якорь
+ Наушники
+ Папка
+ Булавка
+
diff --git a/matrix-sdk-android/src/main/res/values-sk/strings.xml b/matrix-sdk-android/src/main/res/values-sk/strings.xml
index 70e3a6ebd0..da869eacc2 100644
--- a/matrix-sdk-android/src/main/res/values-sk/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-sk/strings.xml
@@ -81,70 +81,6 @@
Odstránená správa používateľom %1$sOdstránená správa [dôvod: %1$s]Odstránená správa používateľom %1$s [dôvod: %2$s]
- Hlava psa
- Hlava mačky
- Hlava leva
- Kôň
- Hlava jednorožca
- Hlava prasaťa
- Slon
- Hlava zajaca
- Hlava pandy
- Kohút
- Tučniak
- Korytnačka
- Ryba
- Chobotnica
- Motýľ
- Tulipán
- Listnatý strom
- Kaktus
- Huba
- Zemeguľa
- Polmesiac
- Oblak
- Oheň
- Banán
- Červené jablko
- Jahoda
- Kukuričný klas
- Pizza
- Narodeninová torta
- Červené srdce
- Škeriaca sa tvár
- Robot
- Cylinder
- Okuliare
- Francúzsky kľúč
- Santa Claus
- Palec nahor
- Dáždnik
- Presýpacie hodiny
- Budík
- Zabalený darček
- Žiarovka
- Zatvorená kniha
- Ceruzka
- Sponka na papier
- Nožnice
- Zatvorená zámka
- Kľúč
- Kladivo
- Telefón
- Kockovaná zástava
- Rušeň
- Bicykel
- Lietadlo
- Raketa
- Trofej
- Futbal
- Gitara
- Trúbka
- Zvon
- Kotva
- Slúchadlá
- Fascikel
- ŠpendlíkÚvodná synchronizácia:
\nPrebieha import účtu…
@@ -299,8 +235,4 @@
%s požaduje overenie vašich šifrovacích kľúčov, ale váš klient nepodporuje overenie kľúčov v konverzácii. Budete musieť použiť zastaralú metódu overenia.
- Prijať
- Odmietnuť
- Zavesiť
-
diff --git a/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml
new file mode 100644
index 0000000000..72fd9cc2a3
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hlava psa
+ Hlava mačky
+ Hlava leva
+ Kôň
+ Hlava jednorožca
+ Hlava prasaťa
+ Slon
+ Hlava zajaca
+ Hlava pandy
+ Kohút
+ Tučniak
+ Korytnačka
+ Ryba
+ Chobotnica
+ Motýľ
+ Tulipán
+ Listnatý strom
+ Kaktus
+ Huba
+ Zemeguľa
+ Polmesiac
+ Oblak
+ Oheň
+ Banán
+ Červené jablko
+ Jahoda
+ Kukuričný klas
+ Pizza
+ Narodeninová torta
+ červené srdce
+ Škeriaca sa tvár
+ Robot
+ Cilinder
+ Okuliare
+ Francúzsky kľúč
+ Santa Claus
+ Palec nahor
+ Dáždnik
+ Presýpacie hodiny
+ Budík
+ Zabalený darček
+ Žiarovka
+ Zatvorená kniha
+ Ceruzka
+ Sponka na papier
+ Nožnice
+ Zatvorená zámka
+ Kľúč
+ Kladivo
+ Telefón
+ Kockovaná zástava
+ Rušeň
+ Bicykel
+ Lietadlo
+ Raketa
+ Trofej
+ Futbal
+ Gitara
+ Trúbka
+ Zvon
+ Kotva
+ Slúchadlá
+ Fascikel
+ Špendlík
+
diff --git a/matrix-sdk-android/src/main/res/values-sq/strings.xml b/matrix-sdk-android/src/main/res/values-sq/strings.xml
index e63e28288f..14a7c61bbc 100644
--- a/matrix-sdk-android/src/main/res/values-sq/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-sq/strings.xml
@@ -77,68 +77,6 @@
Mesazhi u hoq nga %1$sMesazh i hequr [arsye: %1$s]Mesazh i hequr nga %1$s [arsye: %2$s]
- Qen
- Mace
- Luan
- Kalë
- Njëbrirësh
- Derr
- Elefant
- Lepur
- Panda
- Këndes
- Pinguin
- Breshkë
- Peshk
- Oktapod
- Flutur
- Lule
- Pemë
- Kaktus
- Kërpudhë
- Rruzull
- Hëna
- Re
- Zjarr
- Banane
- Mollë
- Luleshtrydhe
- Misër
- Picë
- Tortë
- Zemër
- Emotikon
- Robot
- Kapë
- Syze
- Çelës
- Babagjyshi i Vitit të Ri
- Ombrellë
- Klepsidër
- Sahat
- Dhuratë
- Llambë
- Libër
- Laps
- Kapëse
- Gërshërë
- Dry
- Kyç
- Çekiç
- Telefon
- Flamur
- Tren
- Biçikletë
- Aeroplan
- Raketë
- Trofe
- Top
- Kitarë
- Trombë
- Kambanë
- Spirancë
- Kufje
- Dosje%s e përmirësoi këtë dhomë.Njëkohësimi Fillestar:
@@ -200,6 +138,4 @@
%s po kërkon të verifikojë kyçin tuaj, por klienti juaj nuk mbulon verifikim kyçesh brenda fjalosjeje. Që të verifikoni kyça, do t’ju duhet të përdorni verifikim të dikurshëm kyçesh.%1$s krijo dhomën
- Fiksoje
-
diff --git a/matrix-sdk-android/src/main/res/values-sv/strings.xml b/matrix-sdk-android/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000000..491eb0bc49
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sv/strings.xml
@@ -0,0 +1,224 @@
+
+
+ %1$s: %2$s
+ %1$s skickade en bild.
+ Du skickade en bild.
+ %1$s skickade en dekal.
+ Du skickade en dekal.
+
+ Inbjudan från %s
+ Inbjudan från dig
+ %1$s skapade rummet
+ Du skapade rummet
+ %1$s bjöd in %2$s
+ Du bjöd in %1$s
+ %1$s bjöd in dig
+ %1$s gick med i rummet
+ Du gick med i rummet
+ %1$s lämnade rummet
+ Du lämnade rummet
+ %1$s avböjde inbjudan
+ Du avböjde inbjudan
+ %1$s kickade %2$s
+ Du kickade %1$s
+ %1$s avbannade %2$s
+ Du avbannade %1$s
+ %1$s avbannade %2$s
+ Du bannade %1$s
+ %1$s drog tillbaka inbjudan för %2$s
+ Du drog tillbaka inbjudan för %1$s
+ %1$s ändrade sin avatar
+ Du ändrade din avatar
+ %1$s satte sitt visningsnamn till %2$s
+ Du satte ditt visningsnamn till %1$s
+ %1$s bytte sitt visningsnamn från %2$s till %3$s
+ Du bytte ditt visningsnamn från %1$s till %2$s
+ %1$s tog bort sitt visningsnamn (det var %2$s)
+ Du tog bort ditt visningsnamn (det var %1$s)
+ %1$s bytte ämnet till: %2$s
+ Du bytte ämnet till: %1$s
+ %1$s bytte rummets avatar
+ Du bytte rummets avatar
+ %1$s bytte rummets namn till: %2$s
+ Du bytte rummets namnet till: %1$s
+ %s startade ett videosamtal.
+ Du startade ett videosamtal.
+ %s startade ett röstsamtal.
+ Du startade ett röstsamtal.
+ %s skickade data för att sätta upp samtalet.
+ Du skickade data för att sätta upp samtalet.
+ %s svarade på samtalet.
+ Du svarade på samtalet.
+ %s avslutade samtalet.
+ Du avslutade samtalet.
+ %1$s gjorde framtida rumshistorik synlig för %2$s
+ Du gjorde framtida rumshistorik synlig för %1$s
+ alla rumsmedlemmar, från tiden de bjöds in.
+ alla rumsmedlemmar, från tiden de gick med.
+ alla rumsmedlemmar.
+ vem som helst.
+ okänt (%s).
+ %1$s aktiverade totalsträckskryptering (%2$s)
+ Du aktiverade totalsträckskryptering (%1$s)
+ %s uppgraderade det här rummet.
+ Du uppgraderade det här rummet.
+
+ %1$s begärde ett VoIP-gruppsamtal
+ Du begärde ett VoIP-gruppsamtal
+ VoIP-gruppsamtal startat
+ VoIP-gruppsamtal avslutat
+
+ (avataren blev även bytt)
+ %1$s tog bort rummets namn
+ Du tog bort rummets namn
+ %1$s tog bort rummets ämne
+ Du tog bort rummets ämne
+ %1$s tog bort rummets avatar
+ Du tog bort rummets avatar
+ Meddelande borttaget
+ Meddelande borttaget av %1$s
+ Meddelande borttaget [anledning: %1$s]
+ Meddelande borttaget av %1$s [anledning: %2$s]
+ %1$s uppdaterade sim profil %2$s
+ Du uppdaterade din profil %1$s
+ %1$s bjöd in %2$s att gå med i rummet
+ Du bjöd in %1$s att gå med i rummet
+ %1$s drog tillbaka inbjudan för %2$s att gå med i rummet
+ Du drog tillbaka inbjudan för %1$s att gå med i rummet
+ %1$s accepterade inbjudan för %2$s
+ Du accepterade inbjudan för %1$s
+
+ %1$s lade till %2$s-widget
+ Du lade till %1$s-widget
+ %1$s tog bort %2$s-widget
+ Du tog bort %1$s-widget
+ %1$s modifierade %2$s-widget
+ Du modifierade %1$s-widget
+
+ Admin
+ Moderator
+ Standard
+ Anpassad (%1$d)
+ Anpassad
+
+ Du ändrade behörighetsnivå för %1$s.
+ %1$s ändrade behörighetsnivå för %2$s.
+ %1$s från %2$s till %3$s
+
+ ** Kan inte avkryptera: %s **
+ Avsändarens enhet har inte gett oss nycklarna för det här meddelandet.
+
+ Kunde inte dölja
+ Kunde inte skicka meddelandet
+
+ Misslyckades att ladda upp bilden
+
+ Nätverksfel
+ Matrixfel
+
+ Det går för närvarande inte att gå med i ett tomt rum igen.
+
+ Krypterat meddelande
+
+ E-postadress
+ Telefonnummer
+
+ Inbjudan från %s
+ Rumsinbjudan
+
+ %1$s och %2$s
+
+
+ %1$s och en till
+ %1$s och %2$d till
+
+
+ Tomt rum
+
+ Inledande synk:
+\nImporterar konto…
+ Inledande synk:
+\nImporterar krypto
+ Inledande synk:
+\nImporterar rum
+ Inledande synk:
+\nImporterar anslutna rum
+ Inledande synk:
+\nImporterar inbjudna rum
+ Inledande synk:
+\nImporterar lämnade rum
+ Inledande synk:
+\nImporterar gemenskaper
+ Inledande synk:
+\nImporterar kontodata
+
+ Skickar meddelande…
+ Rensa sändningskö
+
+ Inbjudan från %1$s. Anledning: %2$s
+ Inbjudan från dig. Anledning: %1$s
+ %1$s bjöd in %2$s. Anledning: %3$s
+ Du bjöd in %1$s. Anledning: %2$s
+ %1$s bjöd in dig. Anledning: %2$s
+ %1$s gick med i rummet. Anledning: %2$s
+ Du gick med i rummet. Anledning: %1$s
+ %1$s lämnade rummet. Anledning: %2$s
+ Du lämnade rummet. Anledning: %1$s
+ %1$s avböjde inbjudan. Anledning: %2$s
+ Du avböjde inbjudan. Anledning: %1$s
+ %1$s kickade %2$s. Anledning: %3$s
+ Du kickade %1$s. Anledning: %2$s
+ %1$s avbannade %2$s. Anledning: %3$s
+ Du avbannade %1$s. Anledning: %2$s
+ %1$s bannade %2$s. Anledning: %3$s
+ Du bannade %1$s. Anledning: %2$s
+ %1$s bjöd in %2$s att gå med i rummet. Anledning: %3$s
+ Du bjöd in %1$s att gå med i rummet. Anledning: %2$s
+ %1$s drog tillbaka inbjudan för %2$s att gå med i rummet. Anledning: %3$s
+ Du drog tillbaka inbjudan för %1$s att gå med i rummet. Anledning: %2$s
+ %1$s accepterade inbjudan för %2$s. Anledning: %3$s
+ Du accepterade inbjudan för %1$s. Anledning: %2$s
+ %1$s drog tillbaka inbjudan för %2$s. Anledning: %3$s
+ Du drog tillbaka inbjudan för %1$s. Anledning: %2$s
+
+
+ %1$s lade till %2$s som en adress för det här rummet.
+ %1$s lade till %2$s som adresser för det här rummet.
+
+
+
+ Du lade till %1$s som en adress för det här rummet.
+ Du lade till %1$s som adresser för det här rummet.
+
+
+
+ %1$s tog bort %2$s som en adress för det här rummet.
+ %1$s tog bort %2$s som adresser för det här rummet.
+
+
+
+ Du tog bort %1$s som en adress för det här rummet.
+ Du tog bort %2$s som adresser för det här rummet.
+
+
+ %1$s lade till %2$s och tog bort %3$s som adresser för det här rummet.
+ Du lade till %1$s och tog bort %2$s som adresser för det här rummet.
+
+ %1$s satta huvudadressen för det här rummet till %2$s.
+ Du satta huvudadressen för det här rummet till %1$s.
+ %1$s tog bort huvudadressen för det här rummet.
+ Du tog bort huvudadressen för det här rummet.
+
+ %1$s tillät gäster att gå med i rummet.
+ Du tillät gäster att gå med i rummet.
+ %1$s hindrade gäster från att gå med i rummet.
+ Du hindrade gäster från att gå med i rummet.
+
+ %1$s aktiverade totalsträckskryptering.
+ Du aktiverade totalsträckskryptering.
+ %1$s aktiverade totalsträckskryptering (okänd algoritm %2$s).
+ Du aktiverade totalsträckskryptering (okänd algoritm %1$s).
+
+ %s begär att verifiera din nyckel, men din klient stöder inte nyckelverifiering i chatten. Du behöver använda legacynyckelverifiering för att verifiera nycklar.
+
+
diff --git a/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml
new file mode 100644
index 0000000000..1e06452ba5
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katt
+ Lejon
+ Häst
+ Enhörning
+ Gris
+ Elefant
+ Kanin
+ Panda
+ Tupp
+ Pingvin
+ Sköldpadda
+ Fisk
+ Bläckfisk
+ Fjäril
+ Blomma
+ Träd
+ Kaktus
+ Svamp
+ Jordklot
+ Måne
+ Moln
+ Eld
+ Banan
+ Äpple
+ Jordgubbe
+ Majskolv
+ Pizza
+ Tårta
+ Hjärta
+ Smiley
+ Robot
+ Hatt
+ Glasögon
+ Skruvnyckel
+ Tomte
+ Tummen upp
+ Paraply
+ Timglas
+ Klocka
+ Paket
+ Lampa
+ Bok
+ Penna
+ Gem
+ Sax
+ Lås
+ Nyckel
+ Hammare
+ Telefon
+ Flagga
+ Ånglok
+ Cykel
+ Flygplan
+ Raket
+ Trofé
+ Boll
+ Gitarr
+ Trumpet
+ Bjällra
+ Ankare
+ Hörlurar
+ Mapp
+ Häftstift
+
diff --git a/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml b/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml
new file mode 100644
index 0000000000..f979f77250
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Пес
+ Кіт
+ Лев
+ Кінь
+ Єдиноріг
+ Свиня
+ Слон
+ Кріль
+ Панда
+ Когут
+ Пінгвін
+ Черепаха
+ Риба
+ Восьминіг
+ Метелик
+ Квітка
+ Дерево
+ Кактус
+ Гриб
+ Глобус
+ Місяць
+ Хмара
+ Вогонь
+ Банан
+ Яблуко
+ Полуниця
+ Кукурудза
+ Піца
+ Пиріг
+ Серце
+ Посмішка
+ Робот
+ Капелюх
+ Окуляри
+ Гайковий ключ
+ Санта Клаус
+ Великий палець вгору
+ Парасолька
+ Пісковий годинник
+ Годинник
+ Подарунок
+ Лампочка
+ Книга
+ Олівець
+ Спиначка
+ Ножиці
+ Замок
+ Ключ
+ Молоток
+ Телефон
+ Прапор
+ Потяг
+ Велосипед
+ Літак
+ Ракета
+ Приз
+ М\'яч
+ Гітара
+ Труба
+ Дзвін
+ Якір
+ Навушники
+ Тека
+ Кнопка
+
diff --git a/matrix-sdk-android/src/main/res/values-vls/strings.xml b/matrix-sdk-android/src/main/res/values-vls/strings.xml
index 5c9132ed35..f0f2287a8d 100644
--- a/matrix-sdk-android/src/main/res/values-vls/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-vls/strings.xml
@@ -77,73 +77,7 @@
Leeg gesprek
-
- Hound
- Katte
- Leeuw
- Peird
- Eenhoorn
- Zwyn
- Olifant
- Keun
- Panda
- Hoane
- Pinguin
- Schildpadde
- Vis
- Octopus
- Beutervlieg
- Bloem
- Boom
- Cactus
- Paddestoel
- Eirdbol
- Moane
- Wolk
- Vier
- Banoan
- Appel
- Freize
- Mais
- Pizza
- Toarte
- Erte
- Smiley
- Robot
- Hoed
- Bril
- Moersleutel
- Kestman
- Duum omhooge
- Paraplu
- Zandloper
- Klok
- Cadeau
- Gloeilampe
- Boek
- Potlood
- Paperclip
- Schoar
- Hangslot
- Sleutel
- Oamer
- Telefong
- Vlagge
- Tring
- Veloo
- Vlieger
- Rakette
- Trofee
- Bolle
- Gitoar
- Trompette
- Belle
- Anker
- Koptelefong
- Mappe
- Pinne
-
- Initiële synchronisoasje:
+ Initiële synchronisoasje:
\nAccount wor geïmporteerd…Initiële synchronisoasje:
\nCrypto wor geïmporteerd
diff --git a/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml b/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
index ef080e8357..60322821d4 100644
--- a/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
@@ -75,69 +75,6 @@
消息已被 %1$s 移除消息已被移除 [原因: %1$s]消息已被 %1$s 移除 [原因: %2$s]
- 狗
- 猫
- 狮子
- 马
- 独角兽
- 猪
- 大象
- 兔子
- 熊猫
- 公鸡
- 企鹅
- 乌龟
- 鱼
- 章鱼
- 蝴蝶
- 花
- 树
- 仙人掌
- 蘑菇
- 地球
- 月亮
- 云
- 火
- 香蕉
- 苹果
- 草莓
- 玉米
- 披萨
- 蛋糕
- 心
- 微笑
- 机器人
- 帽子
- 眼镜
- 扳手
- 圣诞老人
- 点赞
- 雨伞
- 沙漏
- 钟
- 礼物
- 灯泡
- 书
- 铅笔
- 回形针
- 剪刀
- 锁
- 钥匙
- 锤子
- 电话
- 旗子
- 火车
- 自行车
- 飞机
- 火箭
- 奖杯
- 球
- 吉他
- 喇叭
- 铃铛
- 锚
- 耳机
- 文件夹初始化同步:
\n正在导入账号…初始化同步:
@@ -161,7 +98,6 @@
清除正在发送队列%1$s 撤回了对 %2$s 加入聊天室的邀请
- 置顶%1$s 的邀请。理由:%2$s%1$s 邀请了 %2$s。理由:%3$s
@@ -289,8 +225,4 @@
您已开启端到端加密。您已开启端到端加密(无法识别的算法 %1$s)。
- 接受
- 拒绝
- 挂断
-
diff --git a/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml b/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml
new file mode 100644
index 0000000000..439615735a
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml
@@ -0,0 +1,10 @@
+
+
+
+ 狗
+ 猫
+ 狮子
+ 马
+ 独角兽
+ 猪
+
diff --git a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
index ee2662f143..355890923c 100644
--- a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
@@ -71,75 +71,10 @@
%1$s 和 和其他 %2$d 個人
-
訊息已移除訊息已被 %1$s 移除訊息已移除 [理由:%1$s]訊息已被 %1$s 移除 [理由:%2$s]
- 狗
- 貓
- 獅
- 馬
- 獨角獸
- 豬
- 象
- 兔
- 貓熊
- 公雞
- 企鵝
- 龜
- 魚
- 章魚
- 蝶
- 花
- 樹
- 仙人掌
- 蘑菇
- 地球
- 月亮
- 雲
- 火
- 香蕉
- 蘋果
- 草莓
- 玉米
- 披薩
- 蛋糕
- 心
- 微笑
- 機器人
- 帽子
- 眼鏡
- 扳手
- 聖誕老人
- 讚
- 雨傘
- 沙漏
- 時鐘
- 禮物
- 燈泡
- 書
- 鉛筆
- 迴紋針
- 剪刀
- 鎖
- 鑰匙
- 鎚子
- 電話
- 旗子
- 火車
- 腳踏車
- 飛機
- 火箭
- 獎盃
- 球
- 吉他
- 喇叭
- 鈴
- 錨
- 耳機
- 資料夾
- 別針初始化同步:
\n正在匯入帳號……
@@ -290,8 +225,4 @@
您開啟了端到端加密。您開啟了端到端加密(無法識別的演算法 %1$s)。
- 接受
- 拒絕
- 掛斷
-
diff --git a/matrix-sdk-android/src/main/res/values/strings.xml b/matrix-sdk-android/src/main/res/values/strings.xml
index 0dc64c1b4b..f64ec9926e 100644
--- a/matrix-sdk-android/src/main/res/values/strings.xml
+++ b/matrix-sdk-android/src/main/res/values/strings.xml
@@ -152,137 +152,6 @@
Empty room
-
-
- Dog
-
- Cat
-
- Lion
-
- Horse
-
- Unicorn
-
- Pig
-
- Elephant
-
- Rabbit
-
- Panda
-
- Rooster
-
- Penguin
-
- Turtle
-
- Fish
-
- Octopus
-
- Butterfly
-
- Flower
-
- Tree
-
- Cactus
-
- Mushroom
-
- Globe
-
- Moon
-
- Cloud
-
- Fire
-
- Banana
-
- Apple
-
- Strawberry
-
- Corn
-
- Pizza
-
- Cake
-
- Heart
-
- Smiley
-
- Robot
-
- Hat
-
- Glasses
-
- Wrench
-
- Santa
-
- Thumbs Up
-
- Umbrella
-
- Hourglass
-
- Clock
-
- Gift
-
- Light Bulb
-
- Book
-
- Pencil
-
- Paperclip
-
- Scissors
-
- Lock
-
- Key
-
- Hammer
-
- Telephone
-
- Flag
-
- Train
-
- Bicycle
-
- Airplane
-
- Rocket
-
- Trophy
-
- Ball
-
- Guitar
-
- Trumpet
-
- Bell
-
- Anchor
-
- Headphones
-
- Folder
-
- Pin
-
-
Initial Sync:\nImporting account…Initial Sync:\nImporting cryptoInitial Sync:\nImporting Rooms
@@ -361,8 +230,4 @@
%s is requesting to verify your key, but your client does not support in-chat key verification. You will need to use legacy key verification to verify keys.
- Accept
- Decline
- Hang Up
-
diff --git a/matrix-sdk-android/src/main/res/values/strings_sas.xml b/matrix-sdk-android/src/main/res/values/strings_sas.xml
new file mode 100644
index 0000000000..8a366a22e5
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Dog
+ Cat
+ Lion
+ Horse
+ Unicorn
+ Pig
+ Elephant
+ Rabbit
+ Panda
+ Rooster
+ Penguin
+ Turtle
+ Fish
+ Octopus
+ Butterfly
+ Flower
+ Tree
+ Cactus
+ Mushroom
+ Globe
+ Moon
+ Cloud
+ Fire
+ Banana
+ Apple
+ Strawberry
+ Corn
+ Pizza
+ Cake
+ Heart
+ Smiley
+ Robot
+ Hat
+ Glasses
+ Spanner
+ Santa
+ Thumbs Up
+ Umbrella
+ Hourglass
+ Clock
+ Gift
+ Light Bulb
+ Book
+ Pencil
+ Paperclip
+ Scissors
+ Lock
+ Key
+ Hammer
+ Telephone
+ Flag
+ Train
+ Bicycle
+ Aeroplane
+ Rocket
+ Trophy
+ Ball
+ Guitar
+ Trumpet
+ Bell
+ Anchor
+ Headphones
+ Folder
+ Pin
+
diff --git a/tools/release/download_buildkite_artifacts.py b/tools/release/download_buildkite_artifacts.py
index ef4251a14f..4439c2fb8c 100755
--- a/tools/release/download_buildkite_artifacts.py
+++ b/tools/release/download_buildkite_artifacts.py
@@ -25,9 +25,9 @@ import requests
# This script downloads artifacts from buildkite.
# Ref: https://buildkite.com/docs/apis/rest-api/artifacts#download-an-artifact
-# Those two variable are specific to the RiotX project
+# Those two variables are specific to the Element Android project
ORG_SLUG = "matrix-dot-org"
-PIPELINE_SLUG = "riotx-android"
+PIPELINE_SLUG = "element-android"
### Arguments
diff --git a/tools/templates/RiotXFeature/globals.xml.ftl b/tools/templates/ElementFeature/globals.xml.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/globals.xml.ftl
rename to tools/templates/ElementFeature/globals.xml.ftl
diff --git a/tools/templates/RiotXFeature/recipe.xml.ftl b/tools/templates/ElementFeature/recipe.xml.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/recipe.xml.ftl
rename to tools/templates/ElementFeature/recipe.xml.ftl
diff --git a/tools/templates/RiotXFeature/root/res/layout/fragment.xml.ftl b/tools/templates/ElementFeature/root/res/layout/fragment.xml.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/res/layout/fragment.xml.ftl
rename to tools/templates/ElementFeature/root/res/layout/fragment.xml.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Action.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/Action.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/Action.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/Action.kt.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Activity.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/Activity.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/Activity.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/Activity.kt.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Fragment.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/Fragment.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/Fragment.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/Fragment.kt.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewEvents.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/ViewEvents.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/ViewEvents.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/ViewEvents.kt.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewModel.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/ViewModel.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewState.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/ViewState.kt.ftl
similarity index 100%
rename from tools/templates/RiotXFeature/root/src/app_package/ViewState.kt.ftl
rename to tools/templates/ElementFeature/root/src/app_package/ViewState.kt.ftl
diff --git a/tools/templates/RiotXFeature/template.xml b/tools/templates/ElementFeature/template.xml
similarity index 99%
rename from tools/templates/RiotXFeature/template.xml
rename to tools/templates/ElementFeature/template.xml
index 33d2edfc70..14c718c993 100644
--- a/tools/templates/RiotXFeature/template.xml
+++ b/tools/templates/ElementFeature/template.xml
@@ -2,7 +2,7 @@
diff --git a/tools/templates/configure.sh b/tools/templates/configure.sh
index de7fe7da81..0669ab1312 100755
--- a/tools/templates/configure.sh
+++ b/tools/templates/configure.sh
@@ -16,10 +16,10 @@
# limitations under the License.
#
-echo "Configure RiotX Template..."
+echo "Configure Element Template..."
if [ -z ${ANDROID_STUDIO+x} ]; then ANDROID_STUDIO="/Applications/Android Studio.app/Contents"; fi
{
-ln -s $(pwd)/RiotXFeature "${ANDROID_STUDIO%/}/plugins/android/lib/templates/other"
+ln -s $(pwd)/ElementFeature "${ANDROID_STUDIO%/}/plugins/android/lib/templates/other"
} && {
echo "Please restart Android Studio."
}
diff --git a/vector/build.gradle b/vector/build.gradle
index e55ad31ef3..52ff0dd23c 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -274,7 +274,7 @@ dependencies {
def moshi_version = '1.8.0'
def daggerVersion = '2.25.4'
def autofill_version = "1.0.0"
- def work_version = '2.3.4'
+ def work_version = '2.4.0'
def arch_version = '2.1.0'
def lifecycle_version = '2.2.0'
diff --git a/vector/src/main/assets/open_source_licenses.html b/vector/src/main/assets/open_source_licenses.html
index 17557b7eb3..376745e6f7 100755
--- a/vector/src/main/assets/open_source_licenses.html
+++ b/vector/src/main/assets/open_source_licenses.html
@@ -313,11 +313,6 @@ SOFTWARE.
Copyright (c) 2012-2016 Dan Wheeler and Dropbox, Inc.
-
- Compressor
-
- Copyright (c) 2016 Zetra.
-
com.otaliastudios:autocomplete
diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 591d1c0474..d0e4c938cd 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -103,6 +103,7 @@ import im.vector.app.features.settings.ignored.VectorSettingsIgnoredUsersFragmen
import im.vector.app.features.settings.locale.LocalePickerFragment
import im.vector.app.features.settings.push.PushGatewaysFragment
import im.vector.app.features.settings.push.PushRulesFragment
+import im.vector.app.features.settings.threepids.ThreePidsSettingsFragment
import im.vector.app.features.share.IncomingShareFragment
import im.vector.app.features.signout.soft.SoftLogoutFragment
import im.vector.app.features.terms.ReviewTermsFragment
@@ -313,6 +314,11 @@ interface FragmentModule {
@FragmentKey(VectorSettingsDevicesFragment::class)
fun bindVectorSettingsDevicesFragment(fragment: VectorSettingsDevicesFragment): Fragment
+ @Binds
+ @IntoMap
+ @FragmentKey(ThreePidsSettingsFragment::class)
+ fun bindThreePidsSettingsFragment(fragment: ThreePidsSettingsFragment): Fragment
+
@Binds
@IntoMap
@FragmentKey(PublicRoomsFragment::class)
diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
index 051847321a..43395b97f7 100644
--- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
+++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
@@ -59,35 +59,46 @@ class DefaultErrorFormatter @Inject constructor(
}
is Failure.ServerError -> {
when {
- throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
+ throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
// Special case for terms and conditions
stringProvider.getString(R.string.error_terms_not_accepted)
}
- throwable.isInvalidPassword() -> {
+ throwable.isInvalidPassword() -> {
stringProvider.getString(R.string.auth_invalid_login_param)
}
- throwable.error.code == MatrixError.M_USER_IN_USE -> {
+ throwable.error.code == MatrixError.M_USER_IN_USE -> {
stringProvider.getString(R.string.login_signup_error_user_in_use)
}
- throwable.error.code == MatrixError.M_BAD_JSON -> {
+ throwable.error.code == MatrixError.M_BAD_JSON -> {
stringProvider.getString(R.string.login_error_bad_json)
}
- throwable.error.code == MatrixError.M_NOT_JSON -> {
+ throwable.error.code == MatrixError.M_NOT_JSON -> {
stringProvider.getString(R.string.login_error_not_json)
}
- throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
+ throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
stringProvider.getString(R.string.login_error_threepid_denied)
}
- throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
+ throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
limitExceededError(throwable.error)
}
- throwable.error.code == MatrixError.M_THREEPID_NOT_FOUND -> {
+ throwable.error.code == MatrixError.M_THREEPID_NOT_FOUND -> {
stringProvider.getString(R.string.login_reset_password_error_not_found)
}
- throwable.error.code == MatrixError.M_USER_DEACTIVATED -> {
+ throwable.error.code == MatrixError.M_USER_DEACTIVATED -> {
stringProvider.getString(R.string.auth_invalid_login_deactivated_account)
}
- else -> {
+ throwable.error.code == MatrixError.M_THREEPID_IN_USE
+ && throwable.error.message == "Email is already in use" -> {
+ stringProvider.getString(R.string.account_email_already_used_error)
+ }
+ throwable.error.code == MatrixError.M_THREEPID_IN_USE
+ && throwable.error.message == "MSISDN is already in use" -> {
+ stringProvider.getString(R.string.account_phone_number_already_used_error)
+ }
+ throwable.error.code == MatrixError.M_THREEPID_AUTH_FAILED -> {
+ stringProvider.getString(R.string.error_threepid_auth_failed)
+ }
+ else -> {
throwable.error.message.takeIf { it.isNotEmpty() }
?: throwable.error.code.takeIf { it.isNotEmpty() }
}
@@ -102,6 +113,7 @@ class DefaultErrorFormatter @Inject constructor(
throwable.localizedMessage
}
}
+ is SsoFlowNotSupportedYet -> stringProvider.getString(R.string.error_sso_flow_not_supported_yet)
else -> throwable.localizedMessage
}
?: stringProvider.getString(R.string.unknown_error)
diff --git a/vector/src/main/java/im/vector/app/core/error/SsoFlowNotSupportedYet.kt b/vector/src/main/java/im/vector/app/core/error/SsoFlowNotSupportedYet.kt
new file mode 100644
index 0000000000..7b22072c34
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/error/SsoFlowNotSupportedYet.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.error
+
+class SsoFlowNotSupportedYet : Throwable()
diff --git a/vector/src/main/java/im/vector/app/core/extensions/ThreePid.kt b/vector/src/main/java/im/vector/app/core/extensions/ThreePid.kt
new file mode 100644
index 0000000000..5d91370963
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/extensions/ThreePid.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.extensions
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil
+import org.matrix.android.sdk.api.extensions.ensurePrefix
+import org.matrix.android.sdk.api.extensions.tryThis
+import org.matrix.android.sdk.api.session.identity.ThreePid
+
+fun ThreePid.getFormattedValue(): String {
+ return when (this) {
+ is ThreePid.Email -> email
+ is ThreePid.Msisdn -> {
+ tryThis(message = "Unable to parse the phone number") {
+ PhoneNumberUtil.getInstance().parse(msisdn.ensurePrefix("+"), null)
+ }
+ ?.let {
+ PhoneNumberUtil.getInstance().format(it, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL)
+ }
+ ?: msisdn
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
index 9ac8a4d3bc..2a17c2ca1b 100644
--- a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
+++ b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
@@ -26,13 +26,15 @@ import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.media.ImageContentRenderer
-import org.matrix.android.sdk.api.Matrix
import okhttp3.OkHttpClient
-import okhttp3.Request
+import org.matrix.android.sdk.api.MatrixCallback
+import org.matrix.android.sdk.api.session.file.FileService
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.io.InputStream
+import java.lang.Exception
+import java.lang.IllegalArgumentException
class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessionHolder)
: ModelLoaderFactory {
@@ -84,10 +86,14 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde
override fun cancel() {
if (stream != null) {
try {
+ // This is often called on main thread, and this could be a network Stream..
+ // on close will throw android.os.NetworkOnMainThreadException, so we catch throwable
stream?.close() // interrupts decode if any
stream = null
- } catch (ignore: IOException) {
- Timber.e(ignore)
+ } catch (ignore: Throwable) {
+ Timber.e("Failed to close stream ${ignore.localizedMessage}")
+ } finally {
+ stream = null
}
}
}
@@ -99,26 +105,48 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde
callback.onDataReady(initialFile.inputStream())
return
}
- val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
- val url = contentUrlResolver.resolveFullSize(data.url)
- ?: return
+// val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
- val request = Request.Builder()
- .url(url)
- .build()
+ val fileService = activeSessionHolder.getSafeActiveSession()?.fileService() ?: return Unit.also {
+ callback.onLoadFailed(IllegalArgumentException("No File service"))
+ }
+ // Use the file vector service, will avoid flickering and redownload after upload
+ fileService.downloadFile(
+ downloadMode = FileService.DownloadMode.FOR_INTERNAL_USE,
+ mimeType = data.mimeType,
+ id = data.eventId,
+ url = data.url,
+ fileName = data.filename,
+ elementToDecrypt = data.elementToDecrypt,
+ callback = object: MatrixCallback {
+ override fun onSuccess(data: File) {
+ callback.onDataReady(data.inputStream())
+ }
- val response = client.newCall(request).execute()
- val inputStream = response.body?.byteStream()
- Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${inputStream?.available()}")
- if (!response.isSuccessful) {
- callback.onLoadFailed(IOException("Unexpected code $response"))
- return
- }
- stream = if (data.elementToDecrypt != null && data.elementToDecrypt.k.isNotBlank()) {
- Matrix.decryptStream(inputStream, data.elementToDecrypt)
- } else {
- inputStream
- }
- callback.onDataReady(stream)
+ override fun onFailure(failure: Throwable) {
+ callback.onLoadFailed(failure as? Exception ?: IOException(failure.localizedMessage))
+ }
+ }
+ )
+// val url = contentUrlResolver.resolveFullSize(data.url)
+// ?: return
+//
+// val request = Request.Builder()
+// .url(url)
+// .build()
+//
+// val response = client.newCall(request).execute()
+// val inputStream = response.body?.byteStream()
+// Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${inputStream?.available()}")
+// if (!response.isSuccessful) {
+// callback.onLoadFailed(IOException("Unexpected code $response"))
+// return
+// }
+// stream = if (data.elementToDecrypt != null && data.elementToDecrypt.k.isNotBlank()) {
+// Matrix.decryptStream(inputStream, data.elementToDecrypt)
+// } else {
+// inputStream
+// }
+// callback.onDataReady(stream)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt b/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
index e3b4430fe0..3bb50c6284 100755
--- a/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
@@ -26,6 +26,7 @@ import im.vector.app.R
import im.vector.app.core.extensions.vectorComponent
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.session.user.model.User
+import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
class UserAvatarPreference : Preference {
@@ -34,6 +35,8 @@ class UserAvatarPreference : Preference {
private var avatarRenderer: AvatarRenderer = context.vectorComponent().avatarRenderer()
+ private var userItem: MatrixItem.UserItem? = null
+
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
@@ -50,9 +53,16 @@ class UserAvatarPreference : Preference {
super.onBindViewHolder(holder)
mAvatarView = holder.itemView.findViewById(R.id.settings_avatar)
mLoadingProgressBar = holder.itemView.findViewById(R.id.avatar_update_progress_bar)
+ refreshUi()
}
fun refreshAvatar(user: User) {
- mAvatarView?.let { avatarRenderer.render(user.toMatrixItem(), it) }
+ userItem = user.toMatrixItem()
+ refreshUi()
+ }
+
+ private fun refreshUi() {
+ val safeUserItem = userItem ?: return
+ mAvatarView?.let { avatarRenderer.render(safeUserItem, it) }
}
}
diff --git a/vector/src/main/java/im/vector/app/core/services/VectorService.kt b/vector/src/main/java/im/vector/app/core/services/VectorService.kt
index 223d720d8a..888f7a8cac 100644
--- a/vector/src/main/java/im/vector/app/core/services/VectorService.kt
+++ b/vector/src/main/java/im/vector/app/core/services/VectorService.kt
@@ -17,10 +17,8 @@
package im.vector.app.core.services
import android.app.Service
-import android.content.Context
import android.content.Intent
import android.os.IBinder
-import im.vector.app.core.extensions.vectorComponent
import timber.log.Timber
/**
@@ -33,10 +31,6 @@ abstract class VectorService : Service() {
*/
private var mIsSelfDestroyed = false
- override fun attachBaseContext(base: Context) {
- super.attachBaseContext(vectorComponent().vectorConfiguration().getLocalisedContext(base))
- }
-
override fun onCreate() {
super.onCreate()
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
index 832250fab4..492df9eb00 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
@@ -70,6 +70,9 @@ abstract class GenericItem : VectorEpoxyModel() {
@EpoxyAttribute
var buttonAction: Action? = null
+ @EpoxyAttribute
+ var destructiveButtonAction: Action? = null
+
@EpoxyAttribute
var itemClickAction: Action? = null
@@ -109,6 +112,11 @@ abstract class GenericItem : VectorEpoxyModel() {
buttonAction?.perform?.run()
}
+ holder.destructiveButton.setTextOrHide(destructiveButtonAction?.title)
+ holder.destructiveButton.setOnClickListener {
+ destructiveButtonAction?.perform?.run()
+ }
+
holder.root.setOnClickListener {
itemClickAction?.perform?.run()
}
@@ -122,5 +130,6 @@ abstract class GenericItem : VectorEpoxyModel() {
val accessoryImage by bind(R.id.item_generic_accessory_image)
val progressBar by bind(R.id.item_generic_progress_bar)
val actionButton by bind
KezdőlapMűveletek
- Rázd meg ha hibát szeretnél bejelenteni
+ Rázd meg az eszközt, ha hibát szeretnél bejelenteni1 tagság változás
@@ -797,8 +799,8 @@ Figyelmeztetés: ez a fájl törlésre kerülhet, ha az alkalmazást törli.%d szoba
- %1$s szoba találat ehhez: %2$s
- %1$s szoba találat ehhez: %2$s
+ %1$s szoba található ehhez: %2$s
+ %1$s szoba található ehhez: %2$s1 olvasatlan üzenet
@@ -842,12 +844,12 @@ Figyelmeztetés: ez a fájl törlésre kerülhet, ha az alkalmazást törli.Matrica küldéseMatrica küldése
- Nincs semmilyen matrica csomagod.
+ Jelenleg nincs matricacsomag bekapcsolva.
\n
-\nHozzáadsz párat most\?
+\nHozzáadsz most párat\?Fiók felfüggesztése
- Függessze fel a fiókomat
+ Saját fiók felfüggesztéseAnalitikai adatok küldéseElement anonim analitikai adatokat gyűjt, hogy javítani tudjuk az alkalmazást.
@@ -872,27 +874,27 @@ Matrixban az üzenetek láthatósága hasonlít az e-mailre. Az üzenet törlés
Harmadik felektől származó licencekLetöltés
- Beszélj
+ BeszédTörlésVégpontok közötti titkosításhoz használt kulcsok újrakérése a többi munkamenetedtől.Kulcs újrakérve.Kérés elküldve
- Kérlek indítsd el a Elementot egy olyan eszközön ami ezt az üzenetet vissza tudja fejteni, hogy elküldhesse a kulcsot erre a munkamenetre.
+ Índítsd el a Elementet egy olyan eszközön, amely vissza tudja fejteni az üzenetet, hogy elküldhesse a kulcsot ennek a munkamenetnek.Ide írj…
- Hang üzenet küldése
+ Hangüzenet küldésetovább ezzel…
- Sajnálom, nem található külső alkalmazás a művelethez.
+ Nem található külső alkalmazás a művelet befejezéséhez.Hang üzenet küldéseKérlek add meg a jelszavad.
- Kérlek, ha lehetséges a leírást angolul írd.
+ Ha lehetséges, a leírást angolul írd.Titkosított válasz küldése…Válasz küldése (titkosítás nélkül)…Média előnézete küldés előtt
@@ -1026,11 +1028,11 @@ Matrixban az üzenetek láthatósága hasonlít az e-mailre. Az üzenet törlés
HívásokAz alapértelmezett Element csengőhang használata bejövő hívásokhozBejövő hívás csengőhangja
- Csengőhang kiválasztása hívásokhoz:
+ Csengőhang kiválasztása a hívásokhoz:Elfogadás
- Kérlek nézd át és fogadd el a Matrix szerver felhasználói feltételeit:
+ Nézd át és fogadd el a Matrix-kiszolgáló házirendjét:Értesítéshibák felderítéseHibakereső diagnosztika
@@ -1063,16 +1065,16 @@ Kérlek ellenőrizd a fiókbeállításokat.
\n%1$s"Play Services javítása
- Firebase Token
+ Firebase tokenFCM token fogadása sikeres:
%1$sFCM token fogadása sikertelen:
%1$s
- Token Regisztráció
- FCM token sikeresen regisztrálva a Matrix szerveren.
- FCM token regisztrációja sikertelen a Matrix szerveren:
-%1$s
+ Token regisztráció
+ FCM token sikeresen regisztrálva a Matrix-kiszolgálón.
+ FCM token regisztrációja sikertelen a Matrix-kiszolgálón:
+\n%1$sÉrtesítés SzolgáltatásÉrtesítés Szolgáltatás fut.
@@ -1114,11 +1116,11 @@ A következő képernyőn el kell fogadnod, hogy a Element folyamatosan fusson a
Érvényes Google Play Services APK nem található. Az értesítések megbízhatatlanul működhetnek.
- Videóhívás folyamatban…
+ Videohívás folyamatban…KulcsmentésKulcsmentés használata
- A kulcsok biztonsági mentése még tart, kérlek várj…
+ A kulcsok biztonsági mentése még tart, kis türelmet…KihagyásKész
@@ -1304,8 +1306,8 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Figyelmen kívül hagyásBelépés egyszeri bejelelentkezéssel
- Ez az URL elérhetetlen, kérlek ellenőrizd
- Az eszközöd elavult TLS biztonsági protokollt használ ami támadható, a biztonságod érdekében nem csatlakozhatsz
+ Ez az URL nem érhető el, ellenőrizd
+ Az eszközöd elavult TLS biztonsági protokollt használ, amely támadható, a biztonságod érdekében nem csatlakozhatszÜzenet küldése Enter billentyűvelAz Enter billentyű a virtuális billentyűzeten elküldi az üzenetet és nem új sort szúr be
@@ -1498,7 +1500,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Segítség & Névjegy
- „Token” regisztrálás
+ Token regisztrálásaJavaslat tételA javaslatodat kérlek ír le alulra.
@@ -1567,20 +1569,20 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
BontásNincs beállítva azonosítási kiszolgáló.
- A hívás sikertelen a hibásan beállított szerver miatt
- Kérd meg a matrix szervered (%1$s) adminisztrátorát, hogy állítson be egy TURN szervert, hogy a hívások megbízhatóan működjenek.
+ A hívás a hibásan beállított kiszolgáló miatt sikertelen
+ Kérd meg a Matrix-kiszolgálód (%1$s) rendszergazdáját, hogy állítson be egy TURN-kiszolgálót, hogy a hívások megbízhatóan működjenek.
\n
-\nAlternatív megoldásként használhatod a nyilvános szervert itt: %2$s, de ez lehet, hogy nem lesz annyira megbízható és az IP címedet megosztja a szerverrel. Ezt a Beállításokban tudod megadni.
+\nAlternatív megoldásként használhatod az itteni nyilvános kiszolgálót: %2$s, de ez lehet, hogy nem lesz annyira megbízható és megosztja az IP-címedet a kiszolgálóval. Ezt a Beállításokban is meg tudod adni.Próbáld ki ezt: %s
- Ne kérdezz újra
+ Ne kérdezze újra
- Fiók visszaállításhoz e-mail beállítása, később esetleg megtalálhatnak akik ismernek téged.
- Telefonszám beállítása, és később esetleg megtalálhatnak akik ismernek téged.
- Fiók visszaállításhoz e-mail beállítás. Később esetleg e-mail vagy telefonszám alapján megtalálhatnak akik ismernek téged.
- Fiók visszaállításhoz e-mail beállítás. Később esetleg e-mail vagy telefonszám alapján megtalálhatnak akik ismernek téged.
- A matrix szerver elérhetetlen ezen a címen, kérlek ellenőrizd
- Tartalék hívás segítő szerver engedélyezése
- Segítségként %s lesz használatban ha a matrix szervered nem ajánl fel egyet (a hívás ideje alatt az IP címed megosztásra kerül)
+ Állíts be egy e-mail címet fiók visszaállításhoz, és hogy később megtalálhassanak akik ismernek.
+ Állíts be egy telefonszámot, hogy megtalálhassanak akik ismernek.
+ Állíts be egy e-mail címet fiók visszaállításhoz. E-mail vagy telefonszám alapján megtalálhatnak akik ismernek.
+ Állíts be egy e-mail címet fiók visszaállításhoz. Később e-mail vagy telefonszám alapján megtalálhatnak akik ismernek.
+ Nem érhető el Matrix-kiszolgáló ezen a címen, ellenőrizd
+ Tartalék hívássegítő kiszolgáló engedélyezése
+ Segítőként a(z) %s lesz használatban ha a Matrix-kiszolgálója nem biztosít egyet (a hívás ideje alatt az IP-címed megosztásra kerül)A beállításokban adj hozzá egy azonosítási szervert ehhez a művelethez.Háttér Szinkronizálási Mód (Kísérleti)Optimalizált akkumulátor használat
@@ -1676,7 +1678,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Tartalom bejelentéseA tartalom bejelentésének okaJELENTÉS
- FELHASZNÁLÓ BLOKKOLÁSA
+ FELHASZNÁLÓ FIGYELMEN KÍVÜL HAGYÁSATartalom bejelentveEz a tartalom bejelentve.
@@ -1722,7 +1724,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Profilképed URL-jeFelhasználói azonosítódTémád
- Kisalkalmazás azon.
+ Kisalkalmazás-azonosítóSzoba azonosító
@@ -1733,8 +1735,8 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Mikrofon használataDRM-mel védett média olvasása
- Ez nem egy érvényes Matrix szerver cím
- Felhasználó tiltása
+ Ez nem egy érvényes Matrix-kiszolgáló címe
+ Felhasználó figyelmen kívül hagyásaMinden üzenet (hangos)Minden üzenet
@@ -1756,7 +1758,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
%1$s beállította, hogy a szobába csak meghívóval lehessen belépni.Olvasatlan üzenetek
- Szabadítsd fel a kommunikációdat
+ Szabadítsd fel a kommunikációdat.Beszélgess másokkal közvetlenül vagy csoportosanBeszélgess bizalmasan, titkosítást használvaBővítsd és szabd testre a élményt
@@ -1914,7 +1916,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Haladó beállításokFejlesztői módA fejlesztői móddal rejtett lehetőségeket kapcsolsz be amitől az alkalmazás instabilabb lehet. Csak fejlesztőknek!
- Rageshake
+ Dühös rázásÉszlelési határAz észlelési határ kipróbálásához rázd meg a telefonodatRázás észlelése sikeres!
@@ -2050,13 +2052,13 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Eszközök közti hitelesítés
- Az eszközök közötti hitelesítés engedélyezve van
-\nPrivát Kulcsok az eszközön.
- Az eszközök közötti hitelesítés engedélyezve van
+ Az eszközök közötti hitelesítés engedélyezett.
+\nPrivát kulcsok az eszközön.
+ Az eszközök közötti hitelesítés engedélyezett
\nA kulcsok megbízhatók.
\nA privát kulcsok ismeretlenek
- Az eszközök közötti hitelesítés engedélyezve van.
-\nA kulcsok megbízhatatlanok
+ Az eszközök közötti hitelesítés engedélyezett.
+\nA kulcsok nem megbízhatóakEszközök közti hitelesítés nincs engedélyezve
@@ -2071,8 +2073,8 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
A munkamenet megbízhatónak való jelöléséhez és a titkosított üzenetekhez való hozzáférés engedélyezéséhez hitelesítsd azt. Ha nem te jelentkeztél be ebbe a munkamenetbe akkor lehetséges, hogy a fiókodat feltörték:
- %d munkamenet használatban
- %d munkamenet használatban
+ %d aktív munkamenet
+ %d aktív munkamenetMunkamenet ellenőrzése
@@ -2114,8 +2116,8 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
%d szavazat
- Végeredmény - %d szavazat
- Végeredmény - %d szavazat
+ %d szavazat – Végeredmény
+ %d szavazat – VégeredményKiválasztott BeállításokEgyszerű szavazás készítése
@@ -2289,8 +2291,8 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
\nElement DesktopElement iOS
\nElement Android
- vagy másik eszközök közötti hitelesítésre alkalmas Matrix kliensre
- A Element legújabb kliensét használd a többi eszközödön:
+ "vagy más eszközök közötti hitelesítést támogató Matrix-klienst"
+ Az Element legújabb kliensét használd a többi eszközödön:A jelenlegi csoport munkamenet törlését kikényszeríti a titkosított szobábanCsak a titkosított szobákban támogatottHasználd ezt: %1$s vagy ezt: %2$s a továbblépéshez.
@@ -2314,7 +2316,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Kérlek válassz jelszót.Ezt a hivatkozást ellenőrizd le még egyszerA közvetlen üzenetedet nem sikerült elkészíteni. Ellenőrizd azokat a felhasználókat akiket meg szeretnél hívni és próbáld újra.
- Használd a legújabb Elementot a másik eszközödön, úgy mint Element Web, Asztali Element, Element for Android vagy más eszközök közötti hitelesítést támogató másik Matrix klienst
+ "Használd a legújabb Elementet a többi eszközödön, azaz az Element Webet, az Element Desktopot, az Element for Androidot vagy más eszközök közötti hitelesítést támogató Matrix-klienst"Erősítsd meg ebben a bejelentkezésben a személyazonosságodat egy másik munkamenetből, hogy hozzáférhess a titkosított üzenetekhez.%1$s hivatkozás egy másik oldalra visz: %2$s.
\n
@@ -2341,7 +2343,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
MÉDIAFÁJLOK%1$s itt: %2$s
- Bejelentkezés
+ Bejelentkezés Matrix-azonosítóvalLecsatlakozol erről az azonosítási szerverről: %s\?Küldés
@@ -2353,7 +2355,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Vagy, ha már rendelkezel egy fiókkal és tudod a Matrix azonosítódat és jelszavadat használhatod ezt is:Belépés a Matrix azonosítómmal
- Add meg az azonosítódat és jelszavadat
+ Ha van fiókod egy Matrix-kiszolgálón, akkor meg a Matrix-azonosítódat (például @felhasznalo:domain.com) és jelszavadat lent.Felhasználói azonosítóEz nem egy valós felhasználó azonosító. A helyes formátum: „@felhasznalo:matrixszerver.org”Nem található a Matrix szerver. Ellenőrizd az azonosítódat
@@ -2378,16 +2380,16 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
Vagy beírhatsz más azonosítási szerver URL-tAdd meg az azonosítási szerver URL-jétSzünet
- Másol
+ MásolásSikerÉrtesítésekHangeszköz kiválasztásaTelefonHangszóró
- Headset
- Vezeték nélküli headset
- Kamera váltás
+ Fejhallgató
+ Vezeték nélküli fejhallgató
+ KameraváltásElsőHátsóHD kikapcsolása
@@ -2414,4 +2416,189 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
A jelenlegi Kulcsod vagy Jelmondatod ki lesz cserélve erre.Az integrációk ki vannak kapcsolva
+ Lejátszás
+ Eltüntetés
+
+
+ Nincs engedélyed konferenciahívást indítani ebben a szobában
+ Már folyamatban van egy konferencia!
+ Videomegbeszélés indítása
+ Megbeszélés indítása (csak hang)
+ A megbeszélések a Jitsi biztonsági és jogosultsági házirendjét használják. A szobában szereplő összes ember meghívást fog kapni, ha elkezdődik a megbeszélés.
+ Nem hívhatod fel saját magad
+ Nem hívhatod fel saját magad, várj amíg a résztvevők elfogadják a meghívást
+ Kisalkalmazás hozzáadása sikertelen
+ Kisalkalmazás eltávolítása sikertelen
+ Element hívás sikertelen
+ Nem sikerült felépíteni a valós idejű kapcsolatot.
+\nKérd meg a Matrix-kiszolgálód rendszergazdáját, hogy állítson be egy TURN-kiszolgálót, hogy a hívások megbízhatóan működjenek.
+
+ SSL hiba: a partner személyazonossága nem lett megerősítve.
+ Véletlen hívás megakadályozása
+ Meghívás visszavonása
+ Lefokozza magát\?
+ Nem fogja tudni visszavonni ezt a változtatást, mert lefokozza magát, ha Ön az utolsó privilegizált felhasználó a szobában, akkor lehetetlen lesz a jogosultságok visszanyerése.
+ Lefokozás
+
+
+ A felhasználó figyelmen kívül hagyása törli az üzeneteit a közös szobáikban.
+\n
+\nEzt a műveletet bármikor visszavonhatja az általános beállításokban.
+ Felhasználó figyelembe vétele
+ A felhasználó figyelembe vétele után újra meg fog jelenni az összes üzenete.
+ Meghívás visszavonása
+ Biztos, hogy visszavonja a felhasználó meghívását\?
+ a felhasználó kirúgása eltávolítja a szobából.
+\n
+\nHa meg akarja akadályozni, hogy újra csatlakozzon, akkor inkább tiltsa ki.
+ A felhasználó tiltásának visszavonása lehetővé teszi, hogy újra csatlakozzon a szobához.
+
+ Ehhez kapcsold be az „Integrációk engedélyezését” a Beállításokban.
+
+
+ %d kitiltott felhasználó
+ %d kitiltott felhasználó
+
+
+ Kulcsok sikeresen exportálva
+
+
+ %1$d/%2$d kulcs sikeresen importálva.
+ %1$d/%2$d kulcs sikeresen importálva.
+
+
+ MEGTEKINTÉS
+ Aktív kisalkalmazások
+
+
+ Integrációk kezelése
+ Nincs aktív kisalkalmazás
+ A visszaállítási kulcs mentve lett.
+
+ Biztonságos mentés
+ Biztosíték a titkosított üzenetekhez és adatokhoz hozzáférés elvesztése ellen
+
+ Biztonságos mentés beállítása
+
+ A szoba létrejött, de néhány meghívó nem lett elküldve, a következő ok miatt:
+\n
+\n%s
+
+ Az egyesítésnek nem sikerült visszafejtenie egy üzenetet az idővonalon
+ Külön lap hozzáadása az olvasatlan értesítések számára a főképernyőn.
+
+
+ %1$s, %2$s és még %3$d felhasználó olvasta
+ %1$s, %2$s és még %3$d felhasználó olvasta
+
+ Hozzáadás a kedvencekhez
+ Eltávolítás a kedvencek közül
+ Nem változtattál semmit
+ Nyilvánossá tetted a szobát azok számára, akik ismerik a hivatkozást.
+ Meghívásossá tetted a szobát.
+ Add meg a használandó kiszolgáló címét
+
+ Ha nem tudod a jelszavad, akkor lépj vissza és állítsd helyre.
+ Matrica
+
+ Rendszergazdai műveletek
+ Alapértelmezett itt: %1$s
+ A kiszolgáló rendszergazdája alapértelmezetten letiltotta a végpontok közti titkosítást a privát szobákban és közvetlen üzenetekben.
+ Adj meg egy csak általad ismert biztonsági kifejezést a kiszolgálón található titkok védelméhez.
+
+ Ha most megszakítod, akkor elvesztheted a titkosított üzeneteid és adataid, ha elveszted a bejelentkezési adataid.
+\n
+\nA Beállításokban állíthatsz be biztonságos mentést és kezelheted a kulcsaidat.
+
+ Létrehoztad és beállítottad a szobát.
+
+ Ez a fiók letiltásra került.
+
+ Eszközök közti hitelesítés engedélyezése
+ A médiafájl mentése sikertelen
+ Szerepkör megadása
+ Szerepkör
+ Csevegés megnyitása
+ Mikrofon némítása
+ Mikrofon némításának megszüntetése
+ Kamera leállítása
+ Kamera indítása
+
+ Biztonságos mentés beállítása
+
+ Biztonságos mentés
+ A titkosított üzenetekhez és adatokhoz való hozzáférés elvesztésének megakadályozása a titkosítási kulcsok kiszolgálóra mentésével.
+ Beállítás
+ Biztonsági kulcs használata
+ Állíts elő egy biztonsági kulcsot jelszókezelőben vagy széfben történő biztonságos tároláshoz.
+ Biztonsági kifejezés használata
+ Adj meg egy csak általad ismert kifejezést, és készíts egy kulcsot biztonsági mentéshez.
+
+ Biztonsági kulcs mentése
+ A biztonsági kulcsot tárold biztonságosan, például egy jelszókezelőben vagy széfben.
+
+ Biztonsági kifejezés beállítása
+ Adj meg egy csak általad ismert biztonsági kifejezést a kiszolgálón található titkok védelméhez.
+ Biztonsági kifejezés
+ Add meg a biztonsági kifejezést a megerősítéshez.
+
+ Biztonsági kulcs mentése
+ A biztonsági kulcsot tárold biztonságosan, például egy jelszókezelőben vagy széfben.
+
+ Szoba neve
+ Téma
+ Szoba beállításainak módosítása sikeres
+
+ Nem érheted el ezt az üzenetet
+ Várakozás erre az üzenetre, ez eltarthat egy darabig
+ Nem fejthető vissza
+ A végpontok közötti titkosítás miatt lehet hogy várnod kell, hogy valaki üzenet megérkezzen, mert a titkosítási kulcsok nem lettek megfelelően elküldve neked.
+ Nem érheted el ezt az üzenetet, mert a küldő letiltott
+ Nem érheted el ezt az üzenetet, mert a feladó nem bízik a munkamenetedben
+ Nem érheted el ezt az üzenetet, mert a feladó szándékosan nem küldte el a kulcsokat
+ Várakozás a titkosítási előzményekre
+
+ A Riot mostantól Element!
+ Örömmel jelentjük be, hogy nevet változtattunk! Az alkalmazás naprakész, és be vagy jelentkezve a fiókodba.
+ ÉRTEM
+ TOVÁBBI INFORMÁCIÓK
+
+ element
+
+
+ Helyreállítási kulcs mentése ide:
+
+ Hozzáadás a telefonkönyvemből
+ A telefonkönyved üres
+ Telefonkönyv
+ Keresés a névjegyeimben
+ Névjegyek lekérése…
+ A névjegyzéked üres
+ Névjegyzék
+
+ Meghívás visszavonása
+ Visszavonod a meghívást ide: %1$s\?
+
+ %1$s kitiltotta
+ Felhasználó visszaengedése sikertelen
+
+ A leküldéses értesítések ki vannak kapcsolva
+ A leküldéses értesítések bekapcsolásához tekintse át a beállításait
+
+ Hibás kód, %d próbálkozás van hátra
+ Hibás kód, %d próbálkozás van hátra
+
+ Figyelem! Utolsó próbálkozási lehetőség a kiléptetés előtt!
+ Túl sok hiba, kiléptettünk
+ Válassz biztonsági PIN-kódot
+ PIN-kód megerősítése
+ Nem sikerült a PIN-kó ellenőrzése, írj be egy újat.
+ Add meg a PIN-kódot
+ Elfelejtetted a PIN-kódot\?
+ PIN-kód helyreállítása
+ Új PIN-kód
+ A PIN-kód helyreállításához újra be kell jelentkezned, és létre kell hoznod egy újat.
+ PIN-kód bekapcsolása
+ Ha helyre akarod állítani a PIN-kódod, koppints az Elfelejtettem a PIN-kódot feliratra a kijelentkezéshez és helyreállításhoz.
+ Erősítsd meg a PIN-kódot a PIN-kód kikapcsolásához
diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml
index bade2d66b7..9667dbf89c 100644
--- a/vector/src/main/res/values-it/strings.xml
+++ b/vector/src/main/res/values-it/strings.xml
@@ -133,6 +133,10 @@
Invia fileFai una foto o un video
+ Accetta
+ Rifiuta
+ Riaggancia
+
AccediCrea account
@@ -630,7 +634,7 @@
Informazioni sessione del mittenteNome pubblicoNome pubblico
- ID
+ ID sessioneChiave sessioneVerificaImpronta digitale Ed25519
@@ -1728,7 +1732,7 @@
Segnala questo contenutoMotivo della segnalazioneSEGNALA
- BLOCCA UTENTE
+ IGNORA UTENTEContenuto segnalatoQuesto contenuto è stato segnalato.
@@ -1785,7 +1789,7 @@
Leggi media protetti da DRMQuesto non è un indirizzo di server Matrix valido
- Blocca utente
+ Ignora utenteTutti i messaggi (rumoroso)Tutti i messaggi
@@ -2620,4 +2624,34 @@
Conferma il PIN per disattivarloImpedisci chiamate accidentaliChiedi conferma prima di iniziare una chiamata
+ Non hai il permesso di avviare una chiamata di gruppo in questa stanza
+ Una chiamata di gruppo è già in corso!
+ Avvia conferenza video
+ Avvia conferenza audio
+ Le conferenze usano la sicurezza di Jitsi e le sua politica sui permessi. Tutte le persone attualmente nella stanza vedranno un invito per unirsi quando la conferenza è in corso.
+ Non puoi chiamare te stesso
+ Non puoi chiamare te stesso, attendi che i partecipanti accettino l\'invito
+ Aggiunta del widget fallita
+ Rimozione del widget fallita
+
+ %1$d/%2$d chiave importata correttamente.
+ %1$d/%2$d chiavi importate correttamente.
+
+
+ Gestisci integrazioni
+ Nessun widget attivo
+ La stanza è stata creata, ma alcuni inviti non sono stati spediti per il seguente motivo:
+\n
+\n%s
+
+
+ %1$s, %2$s e %3$d altro hanno letto
+ %1$s, %2$s e altri %3$d hanno letto
+
+
+ Codice sbagliato, %d tentativo rimasto
+ Codice sbagliato, %d tentativi rimasti
+
+ Attenzione! Ultimo tentativo rimasto prima di venire disconnesso!
+ Troppi errori, sei stato disconnesso
diff --git a/vector/src/main/res/values-ja/strings.xml b/vector/src/main/res/values-ja/strings.xml
index b48b4f401c..dacaa03450 100644
--- a/vector/src/main/res/values-ja/strings.xml
+++ b/vector/src/main/res/values-ja/strings.xml
@@ -1229,4 +1229,5 @@ Matrixでのメッセージの可視性は電子メールと同様です。メ
元の大きさのまま画像を送信する
+ 自分自身には通話できません
diff --git a/vector/src/main/res/values-kab/strings.xml b/vector/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..a532b40d25
--- /dev/null
+++ b/vector/src/main/res/values-kab/strings.xml
@@ -0,0 +1,1328 @@
+
+
+ kab
+ DZ
+ Latn
+
+ Asentel aceɛlal
+ Asentel n yiḍ
+ Asentel aberkan
+ Awennez n umeẓlu
+ Iznan
+ Taxxamt
+ Iɣewwaren
+ Amazray
+ Asenqed n tɣimit
+
+ Tebɣiḍ s tidet\?
+ Asali…
+
+ IH
+ Sefsex
+ Sekles
+ Ffeɣ
+ Azen
+ Nɣel
+ Ɛawed azen
+ Sfeḍ
+ Tanebdurt
+ Sader
+ Bḍu
+ Ticki
+ Wali aɣbalu
+ Kkes
+ Beddel isem
+ Ula yiwen
+ Ḥwi
+ Ffeɣ seg tuqqna
+ Asiwel urmid
+ Ɣeṛ
+ Agi
+
+
+ Ur tesεiḍ ara tisirag ad tebduḍ asireg s usiwel deg texxamt-a
+ Tukksa n uwiǧit ur teddi ara
+ neɣ
+ Nced
+ Beṛṛa n tuqqna
+ Qbel
+ Zgel
+ Immed
+ Sefsex
+ Ttu
+ Senqed
+ Agwi
+
+ Ffeɣ
+ Tigawin
+ Ffeɣ seg tuqqna
+ Creḍ kullec yettwaɣra
+ Amazray
+ Ldi
+ Mdel
+ Nɣel
+ Sens
+
+ Asentem
+ Asmigel
+ Tuccḍa
+ Yedda
+
+ Agejdan
+ Ilɣa
+ Ismenyifen
+ Imdanen
+ Timɣiwent
+ Timɣiwnin
+
+ Inced-d
+ Tazwart taddayt
+ Ilɣa n unagraw
+
+ Ulac igmad
+ Timɣiwent
+ Akaram n texxamt
+ Nced
+ Timɣiwnin
+ Azen iɣmisen
+ Rnu ɣer texxamt
+ Isem n useqdac
+ Rnu amiḍan
+ Ffeɣ seg tuqqna
+ URL n uqeddac n timagit
+ Nadi
+
+ Ur yeddi ara usiwel ssebba n uqeddac ur nettuswel ara akken iwata
+ Tiliɣri
+ Uɣal ɣer deffir
+ Qqen s unekcum asuf
+ Rnu amiḍan
+ Azen
+ Zgel
+ Azen imayl n uwennez
+ Uɣal ɣer ugdil n tuqqna
+ Awal uffir
+ Awal uffir amaynut
+ Tansa n yimayl
+ Sneqdeɣ tansa-inu n yimayl
+ Awal uffir amaynut ilaq ad yettusekcem.
+ Asenqed n tansa n yimayl ur yeddi ara: wali ma yella tsateḍ ɣef useɣwen yellan deg yimayl
+ Asuter n tsarut yettwazen.
+
+ Aneẓli
+ Alemmas
+ Iḍelli
+ Ass-a
+
+ Isawalen
+ Asiwel yekfa
+ Talɣut
+ IH
+ Kemmel
+
+ Sfeḍ
+ Rnu
+ Taskant
+ Agi
+
+ Ffeɣ seg texxamt
+ Snulfu-d
+
+ Srid
+ Beṛṛa n tuqqna
+ Arurmid
+ Iznan usligen
+ Nced
+ Agi
+ Asefsex n tigtin
+ Suffeɣ
+ Abder
+ Ṣubb deg usellun-ik·im\?
+ Ṣubb deg usellun
+
+
+ Ttu
+
+ Taɣẓint
+
+ Nadi
+ Azen izen yettuwgelhen…
+ Azen tiririt yettuwgelhen…
+ Ur tesεiḍ ara tasiregt ad d-tsuffɣeḍ deg texxamt-a
+ Ittkel
+ Tuffɣa
+ Ttu
+ Imdanen
+ Ifuyla
+ Iɣewwaren
+ Nadi
+ Sizdeg iɛeggalen n texxamt
+ Ulac igmad
+ Bdu adiwenni
+ Rnu taxxamt
+ Iznan i meṛṛa (sɛan ṣṣut)
+ Iznan i meṛṛa
+ Sens imesli
+ Asmenyif
+ Adiwenni uslig
+ Iznan
+ Iɣewwaren
+ Lqem
+ Lqem %s
+ Izerfan ttwaḥerzen
+ Sken isem
+ Imayl
+ Tiliɣri
+ Rnu uṭṭun n tiliɣri
+ Rmed
+
+ Rmed
+
+ Rnu amiḍan
+
+ Amagnu
+ Imesli i yilɣa
+ Sens ilɣa i umiḍan-a
+ Iznan yettwaznen s Bot
+
+ Lqem
+ Izerfan ttwaḥerzen
+ Ilɣa
+ Iseqdacen yettunfen
+ Nniḍen
+ Talqayt
+ Awgelhan
+ Azen ilɣa yettuszemlen
+ Sefrek
+ Sens amiḍan
+ Tagrut
+ Tiselḍin
+ Azen isefka n tesleḍt
+ ID
+ Isem azayez
+ Timeẓri taneggarut
+ Asesteb
+ Awal uffir:
+ Azen
+
+ Iqqen am
+ Aqeddac n timagit
+ Amsefrak n umsidef
+
+ Imsidaf ttwasensen
+ Agrudem n useqdac
+ Tutlayt
+ Asenqed yettṛaǧu
+ Ma ulac aɣilif, senqed imayl-ik/im syen sit ɣef useɣwen i yellan. Akken ara yemmed waya, sit ad tkemmleḍ.
+ Awal uffir
+ Beddel awal n uffir
+ Awal uffir amiran
+ Awal uffir amaynut
+ Tangalt
+ Fren
+ Fren
+ Lbenna
+ Yal tikkelt
+
+ Isem n texxamt
+ Asmenyif
+ Tazwart taddayt
+ Ula yiwen
+
+ Ilɣa
+ Anwa i izemren ad d-iɣer amazray\?
+ Anwa i izemren ad d-yernu ɣer texxamt-a\?
+
+ Yal yiwen
+ Iɛeggalen kan (segmi yebda ufran n textiṛit-a)
+ Iɛeggalen kan (segmi ara d-ttwanecden)
+ Iɛeggalen kan (segmi ara d-ttwarnun)
+
+ Ala imdanen i d-yettusnubegten
+ Iseqdacen i yettwagin
+ Talqayt
+ Tinarimin
+ Asulay n temɣiwent d arussin
+ Asentel
+
+ Asulay n tqimit
+ Asulay n tqimit
+ Tasarut n tɣimit
+ Asenqed
+ Sifeḍ tisura n texxamt E2E
+ Sifeḍ tisura n texxamt
+ Sifeḍ
+ Kter tisura n texxamt E2E
+ Kter tisura n texxamt
+ Kter
+ Yettwasenqed
+ ulac
+
+ Senqed
+ Tabdart taberkant
+ Asenqed n tɣimit
+ URL n uqeddac agejdan
+
+ %d n ulɣu
+ %d n ilɣa
+
+
+ Taxxamt
+ Nek
+ Tuɣzi n tsefsit
+ Amagnu
+ Isem-ik·im yettwaskanen
+ URL n avatar-inek·inem
+ Asulay-ik·m n useqdac
+ Asentel-inek·inem
+ Asulay n yiwiǧit
+ Asulay n texxamt
+
+
+ Sireg
+ Timerna n uwiǧit ulamek.
+ Tuzna n usuter ur teddi ara.
+ Ilaq ad yili uswir n tezmert d ummid ufrir.
+ Ulac-ik/ikem deg texxamt-a.
+ Ur tesεiḍ ara tasiregt ad tgeḍ ayagi deg texxamt-a.
+ Sefrek imsidaf
+ Senqed
+ Bḍu
+ Ttu
+
+ Ɣur-k·m!
+ Tuccḍa n tladna
+ Yeskan tigawt
+ Agi aseqdac s usulay i d-yettunefken
+ Sbadu aswir iǧehden n useqdac
+ Aseqdac Deops s usulay i d-yettunefken
+ Inced iseqdacen s tikci n usulay i texxamt tamirant
+ Ffeɣ seg texxamt
+ Suffeɣ aseqdac s usulay i d-yettunefken
+ Ibeddel isem-inek·inem yettwaskanen
+ Insa
+ Snulfu-d
+ Rnu tamɣiwent
+ Amedya
+ amedya
+
+ Agejdan
+ Imdanen
+ Timɣiwent
+ Timɣiwent
+ Yettwancad
+ Tettuḍ taxxamt
+
+ Sens amiḍan
+ Sens amiḍan
+
+ Aqeddac-a agejdan iɛedda yiwet seg tlisa-ines tiɣbula.
+
+ Aqeddac-a agejdan yewweḍ ɣer talast n useqdac urmid n wayyur.
+
+ snefli
+ fneẓ
+
+ Yal ass
+ Sentem tafyirt tuffirt
+ Sekcem tafyirt tuffirt
+ Bdu aseqdec n uḥraz n tsarut
+ Sifeḍ s ufus tisura
+
+ Immed
+ Bḍu
+ Semselsi
+ Tebɣiḍ s tidet\?
+ Tiririt seg uḥraz
+ Kkes aḥraz
+
+ Kkes aḥraz
+ Bdu aseqdec n uḥraz n tsarut
+
+ Akk tisura ttwaḥerzent
+ Lqem
+ Tuttra n usenqed i d-ikecmen
+ Yettwasenqed!
+ Iznan iɣellsanen akked useqdac-a ttwawgelhen seg yixef ɣer yixef yerna yiwen ur yezmir ad ten-iɣeṛ.
+ Awi-t
+
+ Asuter n usenqed
+ Ẓreg
+ Err
+
+ Ɛreḍ tikkelt-nniḍen
+ Timɣiwent
+ Izen yettwakksen
+ Sken-d iznan yettwakksen
+ Beddel
+ Timɣiwent
+ Iznan usligen
+
+ Akaram n texxamt
+ Amatu
+ Ismenyifen
+ Taɣellist & tbaḍnit
+ Ameslaw & Tavidyut
+ Tallalt & Ɣef
+
+
+ Sken-d ineḍruyen yeffren deg uzray
+
+ Iznan usligen
+
+ Tiwtilin n useqdec
+ Snifel aqeddac n timagit
+ Afaylu
+ Anermis
+ Takamiṛatt
+ Timidelt
+ Iznan i meṛṛa (sɛan ṣṣut)
+ Iznan i meṛṛa
+ Sens imesli
+ Iɣewwaren
+ Rnu inurifen
+ Kkes seg yinuraf
+ Aha bdu tura
+
+ Nniḍen
+ Kemmel
+ Jerred
+ Kcem
+ Γer sdat
+ Imayl
+ Awal uffir amaynut
+
+ Ɣur-k·m!
+ Kemmel
+
+ Sneqdeɣ tansa-inu n yimayl
+
+ Tammug akken iwata!
+ Awal uffir-inek/inem yettuwennez.
+ Asmigel
+ Imayl
+ Imayl (Afrayan)
+ Γer sdat
+
+ Γer sdat
+
+ Γer sdat
+
+ Isem n useqdac
+ Awal uffir
+ Γer sdat
+ Asmigel
+ Asulay n Matrix
+ Qqen
+ Qqen
+ Awal uffir
+ Sfeḍ isefka udmawanen
+ Sfeḍ meṛṛa isefka
+
+ Iɣewwaren
+ Yerna ¯\\_(ツ)_/¯ ɣer yizen n uḍris arewway
+
+ Msaḍan
+ Ur msaḍan ara
+ Afaylu
+ Tesfesxeḍ
+ Tqebleḍ
+ Asuter n usenqed
+ Asenqed n tɣimit
+ Taɣellist
+ Ilɣa
+ Ffeɣ seg texxamt
+ Inedbalen
+ Sagen
+ Inced-d
+ Iseqdacen
+
+ Ɛeddi ɣer tɣuri n wawwaḍ
+
+ Amazray
+
+ Awgelhen seg yixef ɣer yixef ur yeddi ara
+ Rmed awgelhen\?
+ Senqed anekcam-a
+ Iseqdacen-nniḍen yezmer ur tettamnen ara
+ Senqed
+ Yettwasenqed
+ Asmigel
+
+ Yettwattkal
+ Ur yettwattkal ara
+
+ Ales awennez n tsura
+
+ Ih
+ Uhu
+
+ Sentem tukksa
+ Smiren
+
+ Anekcam amaynut. D kečč/kemm\?
+ Tasarut-ik·im n uɛeddi
+ Fakk
+
+ Awgelhen ur yeddi ara
+ Awgelhen ur yermid ara
+ Iznan ideg yella @taxxamt
+ Iznan yettwawgelhen deg yidiwenniyen usriden
+ Iznan yettwawgelhen deg yidiwenniyen n ugraw
+ Mi ara ttwaleqqment texxamin
+ Yuzen izen d aḍris aččuran war ma isegza-t s tukksa n tecreḍt
+
+ Amiḍan-a yettuḥbes.
+
+ Yella uleqqem n uwgelhen
+ Senqed iman-ik•im d wiyaḍ akken ad qqimen yidiwenniyen-ik•im d iɣellsanen
+
+ Seqdec tasarut n uɛeddi
+ Ur yettwawgelhen ara
+ Senqed ansi i d-tkecmeḍ
+ Senqed akk tiqimiyin-ik·im i wakken ad tḍemneḍ amiḍan-ik·m & yiznan d iɣelsanen
+ Senqed s ufus s ttawil n uḍris
+ Azen
+ Sbadu
+ Sekles tasarut-ik·im n tɣellist
+ Sbadu tafyirt taɣelsant
+ Sekles tasarut-ik·im n tɣellist
+ Isem n texxamt
+ Tura, Riot d aferdis!
+ Sefesex tinnubga
+ Asent status.iml
+
+ Amtawi…
+ Timesliwt i yineḍruyen
+ Ilɣa s tsusmi
+
+ Talqayt n uɛeggal
+ Aneqqis n wabug
+ Talqayt n temɣiwent
+ Azen astiker
+ Aḥraz n tsarut
+ Aḥraz n tsarut n useqdac
+ Aḥraz n tsura ur yemmid ara, ttxil-k·m ṛǧu…
+ Ad tesruḥeḍ iznan-ik•im yettwawgelhen ma teffɣeḍ tura
+ Akles n tsura yetteddu. Ma teffɣeḍ tura, ad tesruḥeḍ anekcum ɣer yiznan-ik•im yettwawgelhen.
+ Akles aɣellsan n tsura ilaq ad yermed deg tɣimiyin-ik•im akk akken ur tesruḥuḍ ara anekcum ɣer yiznan-ik•im yettwawgelhen.
+ Ur bɣiɣ ara iznan-iw yettwawgelhen
+ Akles n tsura…
+ Aḥraz n tsarut n useqdac
+ Aḥraz
+ Ad tesruḥeḍ anekcum ɣer yiznan-ik•im yettwawgelhen anagar ma tkelseḍ tisura-inek•inem send tuffɣa.
+ Qqim
+ Mmeslay
+ Sfeḍ
+ Ɣer sdat
+ Aseɣwen imezgi
+ Senqed taɣbalut tawgelhent
+ Agbur n uneqqis
+ Taɣect
+ Ividyuten
+ Ulamek ad yebdu usiwel, ttxil ɛreḍ ticki
+ Asarag ha-t-an itteddu!
+ Bdu timlilit s tvidyut
+ Bdu timlilit tameslawt
+ Timlilit s useqdec n tsertiyin n tɣellist d tsiregt n Jitsi. Medden akk i yellan deg texxamt ad ẓren tinubga i tmerniwt mi ara d-teḍru temlilit.
+ Ulamek ad yebdu usiwel
+ Ur tezmireḍ ara ad tesɛeddiḍ asiwel i yima-ik•im
+ Ur tezmireḍ ara ad tesɛeddiḍ asiwel i yiman-ik•im, rǧu ad qeblen yimettekkiyen tinubga
+ Talɣut ɣef tɣimit
+ Timerniwt n uwiǧit ur teddi ara
+ Izen yettwawgelhen
+
+ Imi xuṣṣent tsirag, izmer ur ttilint ara kra n tmahilin…
+ Tesriḍ tisirag akken ad tebduḍ asarag deg texxamt-a
+ Imi llant tsirag i ixuṣṣen, tigawt-a ur tezmir ara ad tili.
+ Isiwlen isaragen ur ttwasefraken ara deg texxamin yettwawgelhen
+ Ɣas siwel kan
+ Ɣas azen kan
+ D tidet tebɣiḍ ad teffɣeḍ\?
+ Asiwel aɣectan
+ Asiwel s tvidyut
+ Anadi amatu
+ Tiririt taruradt
+ Creḍ yettwaɣṛa
+ Nɣel deg \"ɣef ufus\"
+ Sizdeg ismawen n texxamin
+ Ilɣa s ṣṣut
+ Turagin n wis tlata
+
+ Sgunfu
+ Asarag s usiwel iteddu
+\nRnu-d ɣer-s s %1$s neɣ s %2$s
+ Sizdeg ismenyifen
+ Sizdeg imttekkiyen
+ Sizdeg ismawen n texxxamin
+ Sizdeg ismawen n temɣiwnin
+
+ Idiwenniyen
+ Adlis n tansiwin adigan
+ Akaram n useqdac
+ Inermisen kan n Matrix
+ Ulac idiwenniyen
+ Ur teǧǧiḍ ara Element ad yekcem ɣer yinermisen-ik·im idiganen
+ Ulac aqeddac n timagit yettusiwlen.
+
+ Ulac tixxamin
+ Ulac tixxamin tizuyaz yellan
+
+ 1 useqdac
+ %d yiseqdacen
+
+
+ Ulac igrawen
+
+ Azen iɣmisen n tuccḍa
+ Azen tuṭṭfa n ugdil
+ Ini ɣef wabug
+ Ttxil-k·m glem-d abug. Acu i txedmeḍ\? Acu i terǧiḍ\? Acu yeḍran\?
+ Ma yella wamek, ttxil-k·m aru aglam s teglizit.
+ Glem-d ugur-ik·im da
+ Zelzel reffu i tuzna n wabug
+
+ Yettwazen uneqqis n wabug akken iwata
+ Ur nessaweḍ ara ad nazen aneqqis n wabug (%s)
+ Asfari (%s%%)
+
+ Azen deg
+ Ɣeṛ
+
+ Qqen
+ URL n uqeddac agejdan
+ Yebda udiwenni amaynut
+ Yebda usiwel s taɣect
+ Yebda usiwel s tvidyut
+
+ Azen s taɣuct
+
+ Tebɣiḍ s tidet ad tebduḍ adiwenni amaynut d %s\?
+ Tebɣiḍ s tidet ad tebduḍ asiwel s taɣect\?
+ Tebɣiḍ s tidet ad tebduḍ asiwel s tvidyut\?
+ Ttxil-k·m suter anedbal n uqeddac-ik·im agejdan (%1$s) ad iswel aqeddac i wakken isawalen TURN i wakken isawalen ad ddun akken iwata.
+\n
+\nDeg wadeg n wayen, tzemreḍ ad tesqedceḍ aqeddac azayez ɣef %2$s, maca aya ur yettettkal ara fell-as, ad yebḍu tansa-ik·im IP d uqeddac-a. Tzemreḍ ad tesferkeḍ aya deg yiɣewwaren.
+ Ɛreḍ aseqdec n %s
+ Ur iyi-d-ssutur ara tikkelt-nniḍen
+
+ Asiwel s Element ur yeddi ara
+ Fren ibenk n yimesli
+ Amennay
+ Kask
+ Beddel takamiṛat
+ N sdat
+ Sens HD
+ Rmed HD
+
+ Azen ifuyla
+ Azen astiker
+ Ṭṭef-d tawlaft neɣ tavidyut
+ Ṭṭef-d tawlaft
+ Ṭṭef-d tavidyut
+
+ kemmel s…
+ Suref-aɣ, ulac asnas yeffɣen yettwafen i wakken ad temmed tigawt-a.
+
+ Qqen
+ Imayl neɣ isem n useqdac
+ Isem n useqdac
+ Tansa n yimayl (d tafrayan)
+ Uṭṭun n tiliɣri
+ Uṭṭun n tiliɣri (d afrayan)
+ Ales i wawal uffir
+ Sentem awal-ik·im uffir amaynut
+ Isem n uqeddac d/neɣ awal uffir d arameɣtu
+ Ismawen n yiseqdacen ilaq ad sɛun kan isekkilen, imḍanen, agazen, ijerriden n tuqqna d yidduren n uderrer
+ Awal uffir wezzil aṭas (ma drus 6)
+ Ixuṣ wawal uffir
+ Wagi ur d-yettban ara d uṭṭun n tilifun ameɣtu
+ Tansa-a n yimayl tettuseqdec yakan.
+ Txuṣṣ tansa n yimayl
+ Ixuṣṣ wuṭṭun n tiliɣri
+ Txuṣṣ tansa n yimayl neɣ uṭṭun n tiliɣri
+ Ajuṭu d arameɣtu
+ Awal uffir ur imṣada ara
+ Tettuḍ awal uffir\?
+ Seqdec tixtiṛiyin n uqeddac udmawan (leqqayen)
+ Ttxil-k·m seqdec imayl-ik·im i wakken ad tkemmleḍ ajerred
+ Aqeddac-a agejdan yesra ad iẓer ma mačči d aṛubut i telliḍ
+ Isem n useqdac yettuseqdac
+ Aqeddac agejdan:
+ Aqeddac n timagit:
+ I uwennez n wawal-ik·im uffir, sekcem tansa n yimayl i icudden ɣer umiḍan-ik·im:
+ Tansa n yimayl i icudden ɣer umiḍan-ik·im ilaq ad tettwasekcem.
+ Yettwazen yimayl ɣer %s: Akken ara tḍefreḍ aseɣwen-nni yellan deg-s, sit ddaw.
+ Ttxil-k·m senqed syen qbel tisertiyin n uqeddac-a agejdan:
+
+ Ilaq ad yebdu URL s http[s]://
+ D awezɣi ad tkecmeḍ: tuccḍa deg uzeṭṭa
+ Anekcum d awezɣi
+ D awezɣi ad tjerrdeḍ: tuccḍa deg uzeṭṭa
+ Ajerred d awezɣi
+ D awezɣi ad tjerrdeḍ: tuccḍa deg bab n tansa
+ Ttxil-k·m sekcem URL ameɣtu
+ URL-a ulac awwaḍ ɣur-s, ttxil-k·m senqed-it
+ Tagi mačči d tansa n uqeddac n Matrix ameɣtu
+ Ur tezmireḍ ara ad tawḍeḍ ɣer uqeddac agejdan n URL-a, ttxil-k·m senqed-it
+ Tuccḍa deg SSL: ayugan n timagit ur yettwasenqed ara.
+ Tuccḍa n SSL.
+ Tabdart n yigrawen
+
+ Azen-aɣ-d
+ Hraw
+ Meẓẓiy
+
+ Sefsex asider\?
+ Sefsex asali\?
+ %d s
+ %1$dm %2$ds
+
+ Isem n texxamt
+ Asentel n texxamt
+
+ Siwel
+ Yeqqen asiwel
+ Asiwel yetteqqen…
+ Asiwel…
+ Asiwel i d-ikecmen
+ Asiwel s tvidyut i d-ikecmen
+ Asiwel s taɣect i d-ikecmen
+ Asiwel la iteddu…
+ Asiwel s tvidyut la iteddu…
+ Rmed asiwel (%s)
+ Uɣal ɣer usiwel
+
+ Yettwasekles
+ UHU
+ Tabdart n yiɛeggalen
+ Amtawi…
+ Ɛeddi ɣer yizen amezwaru ur nettwaɣra ara.
+
+ Tettwanecdeḍ ad ternuḍ ɣer %s
+ taxxamt
+ Adiwenni amaynut
+ Rnu aɛeggal
+
+ 1 uɛeggal urmid
+ %d yiɛeggalen urmiden
+
+
+ 1 uɛeggal
+ %d yiɛeggalen
+
+ 1 uɛeggal
+
+
+ 1tasint
+ %dtsinin
+
+
+ 1tesdidt
+ %dtesdidin
+
+
+ 1usrag
+ %dyisragen
+
+
+ 1wass
+ %dwussan
+
+
+ %1$S tura
+ Seg %1$S %2$S
+
+ IFECKA N UNEDBAL
+ SIWEL
+ TIƔIMIYIN
+
+ Sefsex tinubga
+ Ffeɣ si texxamt-a
+ Kkes si texxamt-a
+ Wennez aseqdac amagnu
+ Eg amaẓrag
+ Eg anebdal
+ Asulay n useqdac, Isem neɣ imayl
+ Sken tabdart n tɣimiyin
+ Ur tettizmireḍ ara ad tesfesxeḍ asnifel-a acku tettṣubbuḍ deg usellun-unek·inem, ma yella d kečč·kemm i d aseqdac aneglam n texxamt-a, d awezɣi ad d-terreḍ ula d yiwet n tseglut.
+ Zgel aseqdac
+ Ur yettwazgel ara
+
+ "%1$s, "
+ %1$s d %2$s
+ %1$s %2$s
+
+ Snubget s usaulay
+ INERMISEN IDIGANEN (%d)
+ AKARAM N USEQDAC (%s)
+ Iseqdacen kan n Matrix
+
+ Snubget-d iseqdacen s usulay
+ Imayl neɣ asulay n Matrix
+
+ %s la yettaru…
+ %1$s & %2$s la ttarun…
+ %1$s & %2$s d wiyaḍ la ttarun…
+ Azen izen (ur yettwawgelhen ara)…
+ Azen tiririt (ur yettwawgelhen ara)…
+ Tṛuḥ tuqqna ɣer uqeddac.
+ Iznan ur ttwaznen ara. %1$s neɣ %2$s tura\?
+ Iznan ur ttwaznen ara ssebba n tiltin n tɣimiyin tarussinin . %1$s neɣ %2$s tura\?
+ Wennez kullec
+ Sefsex kullec
+ Wennez iznan ur yettwaznen ara
+ Kkes iznan ur yettwaznen ara
+ Ur yettwaf ara ufaylu
+
+ 1 yizen amaynut
+ %d yiznan imaynuten
+
+
+ Ur ttkal ara
+ Adsil umḍin (%s):
+ D awezɣi ad nsenqed timagit n uqeddac agemmaḍ.
+ YETTWANCED
+ YERNA
+
+ TIXXAMIN
+ IZNAN
+ IMDANEN
+ IFUYLA
+
+ RNU
+ AKARAM
+ INURIFEN
+ TIXXAMIN
+ TAZWART TADDAYT
+ INEBGAWEN
+ Rnu ɣer texxamt
+ Rnu ɣer texxamt
+ Aru asulay n texxamt neɣ isem yettunefken i texxamt
+
+
+ 1 texxamt
+ %d texxamin
+
+ Ffeɣ seg udiwenni
+ Ttu
+ Tasertit tabaḍnit
+
+ Tawlaft n umaɣnu
+ Rnu tansa n yimayl
+ Talɣut n usnas
+ Tasleḍt n usellek
+ Seddu isekyaden
+ Aselkem… (%1$d of %2$d)
+ Ldi iɣewwaren
+
+ Iɣewwaren n umiḍan.
+ Iɣewwaren n tɣimit.
+ Iɣewwaren udmawanen.
+ Tasertit tabaḍnit
+ Tiɣimiyin
+ Sebadu aḥraz aɣelsan
+ Seḥbiber iman-ik·im ɣef uḍegger n unekcum ɣer yiznann & yisefka yettwawgelhe s uḥraz n tsura n uwgelhen ɣef uqeddac-inek·inem.
+ Sentem awal uffir amaynut
+ Amidya
+ 1 umalas
+ Taxxamt-a ur tesɛi ara tansiwin tidiganin
+ Taxxamt-a ur d-teskin ara tasakezt ula i yiwet n temɣiwent
+ Isem n tiɣimit tazayezt yettban i yimdanen wukud tettmeslayeḍ
+ Sentem s userwes gar wayen i d-iteddun d yiɣewwaren n useqdac deg tɣimit-ik·im tayeḍ:
+ Ma yella ur mṣadan ara, taɣellist n teywalt-ik·im tezmer ad tettwaker.
+ Aqeddac yezmer ad yili ulac-it neɣ iɛedda nnig uɛebbi
+ Sɛan ṣṣut
+
+ Ikcemed deg
+ Tugna n umaɣnu
+
+ I wakken ad tkemmle, ttxil-k·m sekcem awal uffir n umiḍan-ik·im:
+ Ur ttamdal ara akk iznan iwgelhanen
+ Aḥraz ue yezmir ara ad yekkes awgelhen s tsarut-a n uɛeddi: ttxil-k·m sefqed ma d tasarut n uɛeddi tameɣtut i teskecmeḍ.
+
+ Ur ttamdal ara akk iznan iwgelhanen
+ Ur ttamdal ara akk iznan iwgelhanen
+ Aḥraz n tsarut n useqdac
+
+ Tiririt n usnirem n uqeddac agejdan d tarameɣtut
+ Idiwenniyen
+ Tisedmirin
+ Tisedmirin
+
+ Azayez
+ Tisedmirin tiruradin
+
+ Ffeɣ seg tuqqna n uqeddac n timagit
+ Yettraǧu
+
+ Issin ugar
+ Tansa
+ Imayl n usenqed ad yettwazen ɣer tbewwaḍt-ik·im n yimayl i usentem n yiɣewwaren n wawal-ik·im uffir.
+ Asnifel n wawal-ik·im uffir ad iwennez akk tisura n uwgelhen seg yixef ɣer yixef deg meṛṛa n tɣimiyin-ik·im, s tririt n umazray n udiwenni awgelhan ur yettwaɣra ara. Sbadu aḥraz n tsarut neɣ sifeḍ tisura n texxamt-ik·im seg texxamt-nniḍen send awennez n wawal-ik·im uffir.
+ Aql-ak·akem teffɣeḍ seg meṛṛa tiɣimiyin syen ur d-teṭṭifeḍ ara akk ilɣa n Push. I wakken ad talseḍ armad n yilɣa, kcem tikkelt-nniḍen ɣef yal ibenk.
+ Tiγimit tamirant
+ Akken ara yettwarmad, awgelhen ur yettizmir ara ad yens.
+
+ Kečč / kem
+
+ Iznan deg texxamt-a ur ttwawgelhen ara seg yixef ɣer yixef.
+ Issin ugar
+ Ugar
+ Ur yettwazgel ara
+
+ Akken ara yettwarmad, awgelhen ur yettizmir ara ad yens.
+
+ Tiɣimit-ik·im tamaynut dayen tettwasenqed tura. Ɣur-s anekcum ɣer yiznan yettwawgelhen, iseqdac-nniḍen daɣen ad asen-d-tban tettwattkal.
+
+ Anedbal-ik·im n uqeddac issens awgelhen seg yixef ɣer yixef s wudem amezwer deg texxamin tusligin & yiznan usriden.
+ Tiɣimiyin
+ S tidet tebɣiḍ ad tekkseḍ aneḍru-a\? Err deg uqerru-k·m ma yella tekkseḍ asnifel n yisem neɣ asentel n texxamt, yemzer asnifel-a ad yettusefsex.
+ neɣ amsaɣ-nniḍen n Matrix yemṣadan d uzmul amdigan
+ Ḥettem tiɣimit n ugraw ara d-yeffɣen akka tura deg texxamt tawgelhant ad tettwakkes
+ Sentem timagit-ik·im s usenqed n yinekcam-a seg yiwet gar tɣimiyin-inek·inem-nniḍen, serreḥ-as ad tekcem ɣer yiznan yettwawgelhen.
+ D awezɣi ad ternuḍ izen-inek·inem uslig. Ttxil-k·m senqed iseqdacen i tebɣiḍ ad d-tnecdeḍ syen ɛreḍ tikkelt-nniḍen.
+
+ Tutlayt tamirant
+ Sebadu aḥraz aɣelsan
+
+ Seḥbiber iman-ik·im ɣef uḍegger n unekcum ɣer yiznann & yisefka yettwawgelhe s uḥraz n tsura n uwgelhen ɣef uqeddac-inek·inem.
+ Tafyirt n tɣellist
+ Asentel
+ Ur yezmir ara ad yekkes awgelhen
+ AWI-T
+ ISSIN UGAR
+
+ aferdis
+
+
+ Sekles tasarut n tririt deg
+
+ Rnu seg yidles n tiliɣri
+ Idles-ik·im n tiliɣri d ilem
+ Adlis n tiliri
+ Nadi deg yinermisen-inu
+ Tiririt n yinermisen-ik·im…
+ Adlis-ik·im n yinermisen d ilem
+ Adlis n yinermisen
+
+ Sefsex tinubga n %1$s\?
+
+ Yettwagi sɣur %1$s
+ Asemmet n useqdac ur yeddi ara
+
+ Ilɣa push nsan
+ Senqed iɣewwaren-ik·im i wakken ad tremdeḍ ilɣa push
+
+ Tuccḍa deg tengalt, %d uneɛruḍ i d-yeqqimen
+ Tuccḍa deg tengalt, %d ineɛruḍen i d-yeqqimen
+
+ Ɣur-k·m! Aneɛruḍ aneggaru send tuffɣa!
+ Aṭas n tuccḍiwin, telliḍ teffɣeḍ seg tuqqna
+ Fren PIN i tɣellist
+ Sentem PIN
+ Asentem n tebzimt ur yeddi ara, ttxil-k·m aru yiwet.
+ Sekcem PIN inek·inem
+ Ttu PIN\?
+ "Wennez tabzimt "
+ Tabzimt tamaynut n
+ I uwennez n PIN-inek·inem, tesriḍ ad talseḍ anekcum syen rnu yiwen.
+ Rmed PIN
+ Ma yella tebɣiḍ ad twennzeḍ PIN-inek·inem, aru ttu PIN i wakken ad teffɣeḍ syen wennez.
+ Sentem PIN i wakken ad tsenseḍ PIN
+ Iwakken ad d-naf uguren, iɣmisen n umsaɣ-a ad ttwaznen akked uneqqis-a n tuccḍa. Aneqqis-a n tuccḍa, akked yiɣmisen d tuṭṭfa n ugdil, ur d-ttbinen ara s wudem azayez. Ma tesmenyifeḍ tuzzna n uḍris-a kan seddaw, ttxil kkes acraḍ i:
+ Kask war tinelwa
+ Ur tettban ara d tansa n yimayl tameɣtut
+ Isem n uqeddac/awal uffir d arameɣtu
+ Ulac deg-s JSON ameɣtu
+ Isem n useqdac-a yettwaseqdac yakan
+ Aseɣwen n yimayl iɣef mazal ur yettusit ara fell-as
+
+ Ales asuter n tsura n uwgelhen seg tɣimiyin-ik·im tiyaḍ.
+
+ Asuter yettwazen
+ Ɣeṛ tabdart n wawwaḍ
+
+
+ 1 usnifel deg umulteɣ
+ %d yisnifal deg umulteɣ
+
+
+ Sewḥel isawalen iɣef ur tebniḍ
+ Suter i usentem send beddu n usiwel
+ "Sireg aqeddac n tallalt n yisawalen "
+ Suffeɣ aseqdac
+ Ssebba n usuffeɣ
+ Agi aseqdac
+ Ssebba n tigtin
+ Asefsex n useqdac
+ Talqayt n texxamt
+
+ 1 i yettufernen
+ %d i yettufernen
+
+ Sefsex Asali
+ Sefsex Asider
+
+ Nadi akaram
+
+ %1$s taxxamt yettwafen i %2$s
+ %1$s taxxamin yettwafen i %2$s
+
+ Anadi n ukaram…
+
+ Ibdaren kan
+ Tabaḍnit n yilɣa
+ Ilɣa n usellek
+ Tabaḍnit tettwasemẓẓi
+ Asnas yesra asireg i wakken ad iseddu tafelwit n ugilal
+ Tinubgiwin i usiwel
+ Seqdec takamiṛat tadigant
+ Azen iznan n taɣuct
+ Bdu asenqed
+ Bḍu war asenqed
+ Asuter n beṭṭu n tsarut
+ Anef i tuttra
+ Sbadu asentel n texxamt
+ Tasusmi
+ Isem n temɣiwent
+ Asulay n temɣiwent
+ Ulac iseqdacen
+
+ Sizdeg iɛeggalen n ugraw
+ Sizdeg tixxamin n yigrawen
+
+
+ 1 uɛeggal
+ %d yiɛaggalen
+
+
+
+ 1 texxamt
+ %d texxamin
+
+ Taɣzint: %1$s
+ Rnu
+ Avaṭar n wawwaḍ
+ Avaṭar n ulɣu
+ Senqed tura
+
+ %1$s:
+ %1$s: %2$s
+ +%d
+ %d+
+ Ḥbes
+
+ Tasarut tririt
+ D nekk
+
+ Alguritm
+ Azmul
+
+ Wali asuter
+ Asenqed n tsarut
+ Asuter yettwasefsex
+ Tuccḍa tarussint
+
+ Yettwanced-d sɣur %s
+
+ Qbel
+ Ḥemmel
+ Rnu taxxamt tamaynut
+ Snifel azeṭṭa
+ Meṛṛa timɣiwnin
+
+ Taxxamt tamaynut
+ RNU
+ Isem n texxamt
+ Yal yiwen yezmer ad yernu ɣer texxamt-a
+ Lqem SDK n Matrix
+ Amussnaw
+ Ilugan n push
+ asnas_id:
+ push_tasarut:
+ asnas_sken_isem:
+ tiɣimit_isem:
+ Url:
+ Amasal:
+
+ Sekles ajuṭu
+
+ Eg asumer
+ Ttxil-k·m aru asumer-ik·im ddaw.
+ Yettaru…
+ (yettwaẓreg)
+
+ Tiẓrigin n yizen
+ Ulac tiẓrigin yettwafen
+
+ Sizdeg idiwenniyen…
+ Isem neɣ asulay (#example:matrix.org)
+
+ Rnu s usulay n Matrix
+ Timerna n texamt…
+ Ɣeṛ deg
+
+
+ Aqeddac n timagit
+ Sken awal uffir
+ Ffer awal uffir
+
+ %1$s, %2$s d %3$d d tɣuri-nniḍen
+ %1$s, %2$s d %3$d d tɣuriyin-nniḍen
+
+ Taɣuri n %1$s, %2$s d %3$s
+ Taɣuri n %1$s d %2$s
+ Taɣuri n %s
+
+ 1 useqdac yeɣra
+ %d yiseqdacen ɣran
+
+
+ Afaylu \'%1$s\' (%2$s) ɣezzif aṭas i usali. Talast d %3$s.
+
+ Tuccḍa deg tuqqna lawan n uneɛruḍ n uceqquf yeddan.
+ Ameslaw
+ Astiker
+ Ur yezmir ara ad ttusqedcen deg yisefka n beṭṭu
+
+ AMIDYA
+ Ulac amidya deg texxamt-a
+ IFUYLA
+ %1$s ɣer %2$s
+ Ulac ifuyla deg texxxamt-a
+
+ D aspam
+ Aneqqis udmawan…
+ Taɣzint i tuzna n ugbur-a
+ ANEQQIS
+ ZGEL ASEQDAC
+
+ Agbur yettwazen
+ Yettwazen d aspam
+ Zgel aseqdac
+
+ Ibdaren kan
+ Ffeɣ si texxamt
+ %1$s ur iga ara akk isnifal
+ Ur tgiḍ ara akk isnifal
+ Aru n wawalen ufranen i tifin n tsedmirt.
+
+ Ur tezgileṣ ula d yiwen useqdac
+
+ %1$s yerra taxxamt d tazayazt i kra n win yessnen aseɣwen.
+ Terriḍ taxxamt d tazayazt i kra n win yessnen aseɣwen.
+ %1$s yerra taxxamt s tinubga kan.
+ Terriḍ taxxamt s tinubga kan.
+ Iznan ur nettwaɣra ara
+
+ D adiwenni-inek·inem. Ṭṭef-itt.
+ Mmeslay d yimdanen srid neɣ deg ugraw
+ Eǧǧ idiwenniyen d usligen s uwgelhen
+ Fren aqeddac
+ Qqen ɣer %1$s
+ Kcem ɣer %1$s
+ Kemmel s SSO
+
+ Tansa n yimeẓla n Element Matrix
+ Sekcem tansa n uqeddac i tebɣiḍ ad tesqedceḍ
+
+ Imayl-a ur iqqin ula ɣer yiwen n umiḍan.
+
+ Wennez awal uffir ɣef %1$s
+ Ulac amiḍan akk amiḍan wuɣur yeqqen yimayl-a
+
+ Senqed tabewwaḍt-ik·im n yimayl
+ Imayl n usenqed yettwazen ɣer %1$s.
+ Sit ɣef useɣwen i usentem n wawal-ik·im uffir. Akken ara tḍefreḍ aseɣwen i yellan deg-s, sit ddaw.
+ Tuɣalin ɣer unekcum
+
+ Sbadu tansa n yimayl
+ Sbadu uṭṭun n tiliɣri
+ Uṭṭun n tiliɣri
+ Uṭṭun n tiliɣri (d afrayan)
+ Sentem uṭṭun n tilifun
+ Sekcem tangalt
+ Azen tikkelt-nniḍen
+ Ffeɣ seg %1$s
+ Isem n useqdac neɣ imayl
+ Isem-a n useqdac yettwamudd
+ Fren matrix.org
+ Fren imeẓla n Element Matrix
+ Fren aqeddac agejdan udmawan
+ Qbel tiwtilin i wakken ad tkemmleḍ
+
+ Ttxil-k·m senqed imayl-ik·im
+ Kcem s usulay n Matrix
+ Kcem s usulay n Matrix
+ Yemmẓer sɣur
+
+ Aql-ak·akem teffɣeḍ
+ Kcem tikkelt-nniḍen
+
+ Aql-ak·akem teffɣeḍ
+ Sfeḍ isefka
+ Sfeḍ isefka
+ Aglam wezzil aṭas
+
+ Amtawi amezwaru…
+
+ Ẓer meṛṛa tiɣimiyin-inu
+ Iɣewwaren leqqayen
+ Askar aneflay
+ Azlaz yettwaf-d!
+ Tiɣimiyin tiyaḍ
+
+ Rmed awgelhen
+ Mačči d aɣelsan
+ Tavidyut.
+ Tugna.
+ Ameslaw
+ Astiker
+
+ Yettṛaǧu…
+ %s yettwasefsex
+ %s yettwaqbal
+ Asenqed yettwazen
+ Yettwasenqed s ufus
+
+ Siggez tangalt-a
+ Ttxil-k·m sekcem tasarut n tririt
+
+ Asirew n tsarut SSSS seg tefyirt tuffirt
+ Asirew n tsarut SSSS seg tefyirt tuffirt (%s)
+ Asirew n tsarut SSSS seg tsarut n tririt
+ %1$s (%2$s)
+
+ Ur yezmir ara ad isekles afaylu n umidya
+ Sbadu awal uffir amaynut n umiḍan…
+
+ Element Web
+\nElement Desktop
+ Element iOS
+\nElement Android
+ Seqdec aferdis aneggaru ɣef yibenkan-nniḍen:
+ Yettusefrak kan deg texxamin yettwawgelhen
+ Seqdec %1$s-inek·inem neɣ seqdec %2$s-inek.inem i wakken ad tkemmleḍ.
+ Aḥraz ur yezmir ara ad yekkes awgelhen s tsarut-a n tririt: ttxil-k·m sefqed ma d tasarut n tririt tameɣtut i teskecmeḍ.
+ Anekcum ɣer uklas aɣelsan ur yeddi ara
+
+ Yettuwgelhen s yibenk ur nettwasenqed ara
+ Senqed anekcam amaynut i ikecmen ɣer umiḍan-ik/im: %1$s
+
+ Senqed anekcam
+ Creḍ yettwaḍman
+
+ Qbel
+ Agwi
+ Ɛelleq
+
+ Ttxil-ik·im fren isem n useqdac.
+ Ttxil-ik·im fren awal uffir.
+ Rnu iɛeggalen
+ NCED
+ Ancad n yiseqdacen…
+ Nced-d iseqdacen
+ Tinubga tettwazen i %1$s
+ Tinubga tettwazen i %1$s d %2$s
+
+ Tinubga tettwazen i %1$s d wayeḍ-nniḍen
+ Tinubga tettwazen i %1$s d %2$d d wiyeḍ
+
+ Ur nezmir ara ad d-nesnubget iseqdacen. Ttxil-k·m wali iseqdac i tebɣiḍ ad d-tesnubegteḍ syen ɛreḍ tikkelt-nniḍen.
+
+ Tutlayin-nniḍen yellan
+ Sali-d tutlayin yellan…
+
+ Ldi tiwtilin n %s
+ Seqdec %1$s
+ Sbadu tamlilt
+ Tamlilt
+ Ldi adiwenni
+ Sgugem asawaḍ
+ Kkes asgugem i usawaḍ
+ Seḥbes takamiṛat
+ Senker takamiṛat
+
+ Aḥraz aɣelsan
+ Seqdec tasarut n tɣellist
+ Sirew tasarut n tɣellist ara tḥerzeḍ deg wadeg yettwaḍemnen, am yimsefrak n wawalen uufiren neɣ deg usenduq.
+ Sbadu tafyirt taɣelsant
+ Kles tasarut-ik·im n tɣellist deg wadeg yettwaḍemnen, am umsefrak n wawalen uffiren neɣ neɣ usenduq.
+
+ Kles tasarut-ik·im n tɣellist deg wadeg yettwaḍemnen, am umsefrak n wawalen uffiren neɣ neɣ usenduq.
+
+ Tbeddleḍ iɣewwaren n texxamt akken iwata
+
+ Ur tezmireḍ ara ad tkecmeḍ ɣer izen-a
+ Aṛaǧu i umazray n uwgelhen
+
+ Asnas yerreẓ tikkelt-nni taneggarut. Tebɣiḍ ad teldiḍ agdil n uneqqis n truẓi\?
+ Akka tura ur tesɛiḍ ara akemmus n yistiker yettwaremden.
+\n
+\nRnu yiwen tura\?
+
+ Sefsex tinubga
+ Taɣzint i tuzna n ugbur-a
+ Talɣut ɣef tɣimit
+ Fren tamurt
+
+ Ttxil-k·m fren tamurt
+ Uṭṭun n tiliɣri
+ Uṭṭun n tiliɣri d arameɣtu i ufran n tmurt
+ Asenqed n wuṭṭun n tilifun
+ Ad naze-n SMS deg-s tangalt n usenqed. Ttxil-k·m sekcem tangalt-a ddaw.
+ Sekcem tangalt n usenqed
+ Tuccḍa mi ara nessentam uṭṭun-ik·im n tilifun
+ Tella-d tuccḍa mi ara nessenqad uṭṭun-ik·im n tilifun.
+ Talut-nnien: %s
+
+ Asekkussem amezwer
+ Taɣbalut n umidyat amezwer
+ Asentel
+ Alguritm
+
+ 1 texxamt
+ %d texxamin
+
+
+ %1$s: %2$s
+ Meẓẓiy
+ Hraw
+ Ttxil-k·m sekcem tasarut n tririt
+ Rmed awgelhen
+
+ Ayagi yezmer ad yeṭṭef kra n wakud, ttxil-k·m ṣṣber.
+ Asbadu n tririt.
+ Tsuliḍ!
+ Eǧǧ-it d aɣelasn
+ Seqdec wa %1$s d azeṭṭa aɣelsan mi ara tettuḍ %2$s-inek·inem.
+
+ Asuffeɣ n tsura n timagit yettwarnan
+ Asirew n tsarut n tɣellist seg tefyirt tuffirt
+ Asbadu n tsarut s wudem amezwar n SSSS
+ Amtawi n tsarut tagejdant
+ Amtawi n tsarut n useqdac
+ Amtawi n tsarut n uzmul asuf
+ Asbadu n uḥraz n tsarut
+
+
+ %2$s & %1$s inek·inem ttusbadun tura.
+\n
+\nEǧǧ-iten d iɣelsanen! Ad ten-teḥwiǧeḍ ad teldiḍ iznan yettwawgelhen d telɣut n tɣellist ma yella tesruḥeḍ akk tiɣimiyin-ik·im yettwaremden.
+
+ <b>Siggez-itt syen kles-itt deg wadeg aɣelsan
+ Sekles-itt ɣef tsarut USB neɣ deg yibenk n uḥraz
+ Nɣel-itt ɣer uklas-ik·im n usigna udmawan
+
+ Ur tezmireḍ ara ad tgeḍ aya seg uziraz
+
+ Asbadu n tefyirt tuffirt n tririt ad ak·am-teḍmen taɣellist & tawaledyawt n yiznan yettwawgelhen, yettwattkalen.
+\n
+\nMa yella ur tebɣiḍ ara ad tesbaduḍ awal uffir n yizen, sirew deg wadeg-is tasarut n yizen.
+ Imi yella uwgelhen seg yixef er yixef, ilaq-ak·am ad terǧuḍ i yizen n walbaɛḍ ad ak·am-id-yaweḍ acku ur ak·am-d-ttwaznent ara tsura akken iwata.
+ Ur tezmireḍ ara ad tkecmeḍ ɣer yizen-a acku tettusweḥleḍ sɣur amazan
+ Ur tezmireḍ ara ad tkecmeḍ ɣer yizen-a acku tiɣimit-ik·im ur tt-yeḍmin ara umazan
+ Ur tezmire ara ad tkecmeḍ ɣer yizen-a acku amazan iɛemmed ur d-yuzin ara tisura
+ S tumert meqqren ara ak-d-nini nbeddel isem! Asnas-ik·im yettwaleqqem, ha-t-an tkecmeḍ ɣer umiḍan-ik·im.
+
diff --git a/vector/src/main/res/values-nb-rNO/strings.xml b/vector/src/main/res/values-nb-rNO/strings.xml
index ab5b4e5c28..d830d40686 100644
--- a/vector/src/main/res/values-nb-rNO/strings.xml
+++ b/vector/src/main/res/values-nb-rNO/strings.xml
@@ -257,7 +257,7 @@
AlgoritmeØkt-IDDet offentlige navnet til en økt er synlig for folkene du kommuniserer med
- ID
+ Økt-IDØktnøkkelVerifiseringEksporter
@@ -345,7 +345,7 @@
Invitert av %sReaksjoner
- Like
+ LikerReaksjonerEndre
@@ -671,7 +671,7 @@
Kan ikke starte samtaleInformasjon om ØktenKonferansesamtaler er ikke støttet i enkrypterte rom
- Ring likevel.
+ Ring likevelSend likevelEr du sikker på at vil logge ut\?Telefonsamtale
@@ -729,4 +729,302 @@
Er du sikker på du vil starte en samtale med %s\?Er du sikker på du vil starte en lydsamtale\?Er du sikker på du vil starte en videosamtale\?
+ Spill av
+ Pause
+ Avslå
+
+
+ Du har ikke rettigheter til å starte en konferansesamtale i dette rommet
+ Det pågår allerede en konferanse!
+ Start videomøte
+ Start lydmøte
+ Møter bruker sikkerhets- og tilgangsregler fra Jitsi. Alle i rommet vil kunne se en invitasjon til møtet mens det pågår.
+ Du kan ikke ringe deg selv
+ Du kan ikke ringe deg selv. Vent til inviterte deltakere godtar invitasjonen
+ Kunne ikke legge til utvidelse
+ Kunne ikke fjerne utvidelse
+ Kopier
+ Suksess
+
+ Varsler
+ Oppringing feilet som følge av feilkonfigurert tjener
+ Prøv med %s
+ Ikke spør meg igjen
+
+ Element samtale feilet
+ Velg lydenhet
+ Telefon
+ Høytaler
+ Hodesett
+ Trådløst hodesett
+ Bytt kamera
+ Foran
+ Bak
+ Slå HD av
+ Slå HD på
+
+ Send filer
+ Send klistremerke
+ Ta bilde eller video
+ Du har ingen pakker med klistremerker slått på.
+\n
+\nLegge til noen nå\?
+
+ fortsett med…
+ Dessverre, kunne ikke finne en passende ekstern applikasjon for å utføre denne handlingen.
+
+ Logg på med single sign-on
+ E-post eller brukernavn
+ Brukernavn
+ E-postadresse (valgfritt)
+ Telefonnummer (valgfritt)
+ Gjenta passord
+ Bekreft ditt nye passord
+ Manglende passord
+ Dette ser ikke ut som en gyldig E-postadresse
+ Dette ser ikke ut som et gyldig telefonnummer
+ Manglende E-postadresse
+ Manglende telefonnummer
+ Manglende E-postadresse eller telefonnummer
+ Passordene samsvarer ikke
+ SSL-feil.
+ For mange forespørsler har blitt sendt
+ Send som
+ Vil du avbryte nedlastingen\?
+ Vil du avbryte opplastingen\?
+ Rommets navn
+
+ 1 aktivt medlem
+ %d aktive medlemmer
+
+ Forlat rommet
+ %1$s for %2$s siden
+
+ Direktemeldinger
+ Forlat dette rommet
+ Fjern fra dette rommet
+ Utnevn til moderator
+ Utnevn til admin
+ Ignorer bruker
+ Ignorer
+
+ Opphev ignorering
+
+ Bannlys bruker
+ "%1$s, "
+ %1$s og %2$s
+ %1$s og %2$s skriver …
+ %1$s, %2$s og andre skriver …
+ Avbryt alle
+
+ 1 ny melding
+ %d nye meldinger
+
+
+ Romdetaljer
+
+ 1 valgt
+ %d valgte
+
+ INVITERT
+ MELDINGER
+ FILER
+
+ Opprett et rom
+ Bli med i rommet
+ Bli med i et rom
+ Betingelser og vilkår
+ Personvernregler
+
+ Legg til E-postadresse
+ Legg til telefonnummer
+ Avanserte varselsinnstillinger
+ Systeminnstillinger.
+ Kontoinnstillinger.
+ Start ved systemoppstart
+ Skru av restriksjoner
+
+ Batterioptimalisering
+ Redusert privatliv
+ Skru på varsler for denne kontoen
+ Skru på varsler for denne økten
+ Skru på skjermen i 3 sekunder
+ Start ved systemoppstart
+ Betingelser og vilkår
+ Tøm mediemellomlager
+
+ Brukerinnstillinger
+ Ignorerte brukere
+ Integreringer
+ Vis lesekvitteringer
+ Send melding med Enter
+ Administrer
+ Sett opp på denne enheten
+ Deaktiver kontoen min
+ Oppdag
+ Behandle dine oppdagelsesinnstillinger.
+ Gi tillatelse
+ Velg et annet alternativ
+
+ Gi tillatelse
+
+ Datasparingsmodus
+ Øktinformasjon
+ Hjemmetjener
+ Tillat integreringer
+ Integreringer er skrudd av
+ Velg språk
+
+ Verifisering avventer
+ Denne E-postadressen ble ikke funnet.
+ Oppdater passord
+ Telefonverifisering
+ Standardkomprimering
+ Merket som:
+
+ Tilgang og synlighet
+ Romtilgang
+ Punkt-til-punkt-kryptering
+ Punkt-til-punkt-kryptering er skrudd på
+ Ugyldig samfunns-ID
+ Offentlig navn
+ Offentlig navn
+ ukjent økt
+ %1$s i %2$s
+ %1$s: %2$s
+ %1$s: %2$s %3$s
+
+ Aktive moduler
+
+
+ Last inn modulen på nytt
+ Bruk kameraet
+ Bruk mikrofonen
+ Behandle integreringer
+ Ingen aktive moduler
+ Vennligst skriv inn passordet ditt.
+ Samtalen fortsetter her
+ Kontakt administrator
+
+ Beklager, det oppstod en feil
+
+ Opprett en passordfrase
+ Bekreft passordfrasen
+ Skriv inn passordfrase
+ Passordfrasen samsvarer ikke
+ Vennligst skriv inn en passordfrase
+ Passordfrasen er for svak
+
+ (Avansert)
+ Velg passordfrase
+ Suksess!
+ Gjenopprettingsnøkkel
+ Skriv inn gjenopprettingsnøkkelen
+
+ Gjenopprett fra sikkerhetskopi
+ Slett sikkerhetskopien
+
+ Slett sikkerhetskopien
+ Begynn verifisering
+ Du bruker ikke noen identitetstjenere
+ Samtaler
+ Legg til reaksjon
+ Meldingen ble slettet
+ Vis fjernede meldinger
+ Vis en stattholder for fjernede meldinger
+ Alle samfunn
+
+ Rom-arkiv
+ Matrix SDK-versjon
+ Hurtigreaksjoner
+
+ Send inn et forslag
+ Krypterer filen …
+ Navn eller ID (#example:matrix.org)
+
+ Filtrer etter brukernavn eller ID …
+
+ Vis redigeringshistorikk
+
+ MEDIA
+ FILER
+ %1$s, kl. %2$s
+ Det er upassende
+ IGNORER BRUKER
+
+ Ignorer bruker
+
+ Spoiler
+ Du ignorerer ikke noen brukere
+
+ Langklikk på et rom for å se flere innstillinger
+
+
+ Tilpassede og avanserte innstillinger
+
+ Koble til %1$s
+ Adresse
+ Sjekk innboksen din
+ Telefonnummer (valgfritt)
+ Bekreft telefonnummer
+ Registrer deg på %1$s
+ Brukernavn eller E-postadresse
+ Det brukernavnet har blitt tatt
+ Matrix-ID
+ Du er logget av
+ Du er logget av
+ Tøm alle data
+
+ Se alle mine økter
+ Skru på kryptering
+ De samsvarer ikke
+ Klistremerke
+
+ Skru på kryptering
+
+ Oppdater
+
+ Din gjenopprettingsnøkkel
+ Avslutt
+
+ Kryptering er skrudd på
+ Kryptering er ikke skrudd på
+ Medlinger som inneholder @room
+ Krypterte meldinger i samtaler under fire øyne
+ Krypterte meldinger i gruppesamtaler
+ Når rom blir oppgradert
+ Feilsøk
+ %1$s (%2$s)
+
+ Velg et nytt kontopassord …
+
+ Ukryptert
+ Legg til medlemmer
+ Inviterer brukere …
+ Inviter brukere
+ Nåværende språk
+ Andre tilgjengelige språk
+ Bruk %1$s
+ Send
+ Rolle
+ Demp mikrofonen
+ Opphev demping av mikrofonen
+ Stopp kameraet
+ Start kameraet
+
+ Sett opp
+ Rommets navn
+ Emne
+ Kan ikke dekryptere
+ SKJØNNER
+ LÆR MER
+
+ Telefonkatalogen din er tom
+ Telefonkatalog
+ Søk i mine kontakter
+ Bannlyst av %1$s
+ Bekreft PIN-kode
+ Skriv inn PIN-koden din
+ Glemt PIN-koden\?
+ Skru på PIN-kode
diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml
index 493f1f43fa..9409459279 100644
--- a/vector/src/main/res/values-pt-rBR/strings.xml
+++ b/vector/src/main/res/values-pt-rBR/strings.xml
@@ -9,9 +9,13 @@
MensagensSalaConfigurações
- Detalhes dos membros
+ Detalhes do participanteHistórico
+ Aceitar
+ Recusar
+ Encerrar
+
OKCancelar
@@ -28,12 +32,12 @@
LinkVer código-fonteVer código-fonte descriptografado
- Excluir
+ ApagarRenomearDenunciar conteúdoChamada em andamento
- Chamada em grupo em andamento.↵
-\nEntre como %1$s ou %2$s
+ Chamada em grupo em andamento.
+\nEntre com %1$s ou %2$sVozVídeoNão foi possível iniciar a chamada, tente mais tarde
@@ -254,8 +258,6 @@
Element necessita permissão para acessar seu microfone para realizar chamadas de áudio."
\n
-\n↵
-\n↵
\nPor favor, permita o acesso na próxima tela para fazer a chamada."Element necessita permissão para acessar sua câmera e seu microfone para fazer chamadas de vídeo.↵
\n↵
@@ -275,7 +277,7 @@
Continuar
- Remover
+ ApagarEntrarVisualizarRecusar
@@ -294,16 +296,16 @@
Nova conversaAdicionar uma pessoa
- 1 integrante
+ 1 participante
- Deixar a sala
+ Sair da salaTem certeza de que deseja sair da sala\?
- Você tem certeza que quer remover %s desta conversa?
+ Deseja remover %s desta conversa\?CriarOnline
- Desconectada/o
+ OfflineOciosoFERRAMENTAS DE ADMINISTRAÇÃO
@@ -312,7 +314,7 @@
SESSÕESConvidar
- Deixar esta sala
+ Sair da salaRemover desta salaBanir da salaRemover banimento
@@ -373,21 +375,21 @@
PessoasArquivosConfigurações
- ID mal formatado. Precisa ser um endereço de e-mail ou um ID Matrix, como \'@membrolocal:dominio\'
+ ID mal formatado. Precisa ser um endereço de e-mail ou um ID Matrix, como \'@participantelocal:dominio\'CONVIDADOSENTRARAMMotivo de denunciar este conteúdo
- Você deseja ocultar todas as mensagens deste usuário\?↵
-\n↵
-\nNote que esta ação irá reiniciar o aplicativo e poderá tomar um certo tempo.
+ Deseja ocultar todas as mensagens deste usuário\?
+\n
+\nEsta ação irá reiniciar o aplicativo e poderá demorar um pouco.Cancelar envioCancelar downloadPesquisar
- Filtrar integrantes da sala
+ Pesquisar participantes da salaNenhum resultadoSALASMENSAGENS
@@ -415,7 +417,7 @@
FavoritarDespriorizarConversa direta
- Deixar a conversa
+ Sair da conversaEsquecer
@@ -423,13 +425,13 @@
ConfiguraçõesVersãoTermos e condições
- Avisos de terceiros
+ Licenças de terceirosDireito autoralPolítica de privacidade
- Imagem do perfil
+ Foto de perfilNome e sobrenomeE-mailAdicionar endereço de e-mail
@@ -442,11 +444,11 @@
Ativar notificações nesta sessãoAcender a tela por 3 segundos
- Msgs em conversas diretas
+ Mensagens em conversas individuaisMensagens em salas
- Quando eu sou convidado a uma sala
- Convites para chamadas
- Mensagens enviadas por "bot"
+ Quando eu for convidada(o) a uma sala
+ Recebendo chamada
+ Mensagens enviadas por botsSincronização em segundo planoAtivar a sincronização em segundo plano
@@ -456,12 +458,12 @@
segundosVersão
- versão olm
+ Versão do olmTermos e condições
- Avisos de terceiros
+ Licenças de terceirosDireitos autoraisPolítica de privacidade
- Limpar cache
+ Limpar cache e recarregar
@@ -471,7 +473,7 @@
OutrosAvançadoCriptografia
- Alvos de notificação
+ Aparelhos notificadosContatos locaisPermissão de acesso a contatosPaís da agenda de contatos
@@ -492,7 +494,7 @@
Conectado comoServidor Principal (Home Server)
- Servidor de Identidade (Identity Server)
+ Servidor de identidadeConfirmação pendentePor favor, verifique o seu e-mail e clique no link que está lá. Feito isso, clique em continuar.
@@ -502,9 +504,9 @@
Este endereço de e-mail não foi encontrado.Este número de telefone já está em uso.
- Alterar a senha
+ Alterar senhaSenha atual
- Senha nova
+ Nova senhaConfirme a nova senhaNão consegui atualizar a senhaSua senha foi atualizada
@@ -512,9 +514,9 @@
\n↵
\nNote que esta ação irá reiniciar o aplicativo e pode levar algum tempo.
- Você tem certeza que quer remover este destino de notificação?
+ Deseja deixar de notificar este aparelho\?
- Você tem certeza que quer remover o %1$s %2$s?
+ Deseja remover o %1$s %2$s\?Escolha um país
@@ -552,9 +554,9 @@
Qualquer pessoa
- Apenas integrantes (a partir do momento em que esta opção foi escolhida)
- Apenas integrantes (desde que foram convidados)
- Apenas integrantes (desde que entraram na sala)
+ Apenas participantes (a partir do momento em que esta opção foi escolhida)
+ Apenas participantes (desde que foram convidados)
+ Apenas participantes (desde que entraram na sala)Para fazer um link para uma sala, ela precisa ter um endereço.
@@ -600,7 +602,7 @@
Diretório
- %s estava tentando carregar um ponto específico da linha do tempo desta sala, mas não conseguiu encontrá-lo.
+ %s tentou carregar um trecho específico da conversa desta sala, mas não conseguiu.
@@ -617,7 +619,7 @@
Informação sobre a sessão do remetenteNome público do aparelhoNome
- ID do aparelho
+ ID da sessãoChave da sessãoConfirmaçãoImpressão digital ed25519
@@ -658,10 +660,10 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.
Esta sala contém sessões desconhecidas
- Esta sala contém sessões desconhecidas que não foram confirmadas.↵
-\nIsso significa que não há garantia de que estas sessões realmente pertencem aos usuários identificados.↵
-\nRecomendamos que você faça o processo de confirmação para cada sessão desconhecida antes de continuar, mas você pode reenviar a mensagem sem confirmar os aparelhos, se preferir.↵
-\n↵
+ Esta sala contém sessões desconhecidas que não foram confirmadas.
+\nIsso significa que não há garantia de que estas sessões realmente pertencem aos usuários identificados.
+\nRecomendamos que você faça o processo de confirmação para cada sessão desconhecida antes de continuar, mas você pode reenviar a mensagem sem confirmar os aparelhos, se preferir.
+\n
\nSessões desconhecidas nesta sala:
@@ -685,7 +687,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.Mostrar a hora para todas as mensagensModo de economia de dados
- Interface de usuária(o)
+ AparênciaIdiomaEscolha o idioma
@@ -747,7 +749,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.Som de notificaçãoMensagens que contenham o meu nome e sobrenome
- Mensagens que contenham o meu nome de usuária(o)
+ Mensagens que contenham o meu nome de usuárioVisualização prévia do endereçoMostrar a hora no formato de 12 horasVibrar ao mencionar um usuário
@@ -818,7 +820,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.SalasEntrouem que foi convidada/o
- Filtrar integrantes da comunidade
+ Pesquisar participantes da comunidadeFiltrar salas da comunidadeO(A) administrador(a) desta comunidade não definiu uma descrição longa da mesma.
@@ -832,12 +834,12 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.Abrir cabeçalhoSincronizando…
- %d membro ativo
- %d membros ativos
+ %d participante ativo
+ %d participantes ativos
- %d membro
- %d membros
+ %d participante
+ %d participantes%d nova mensagem
@@ -857,7 +859,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.%d alterações na filiação
- Lista de integrantes
+ Lista de participantes%d mensagem notificada não lida%d mensagens notificadas não lidas
@@ -987,7 +989,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.Define a descrição da salaRemove o usuário com o ID fornecidoAltera o seu nome e sobrenome
- Ativar/Desativar o Markdown
+ Ativar/Desativar a formatação de textoReparar a gestão de aplicativos Matrix
@@ -1008,7 +1010,7 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.não faz com que, por padrão, suas mensagens enviadas sejam apagadas. Se você deseja que suas mensagens também sejam apagadas, marque a opção abaixo.↵
\n↵
\nA visibilidade de mensagens na Matrix é semelhante a um e-mail. O fato de apagarmos suas mensagens significa que suas mensagens enviadas não serão compartilhadas com nenhum usuário novo ou ainda não registrado, mas os usuários registrados que já tiveram acesso a essas mensagens ainda terão acesso uma cópia delas.
- Quando minha conta for desativada, exclua todas as mensagens que eu enviei (Atenção: isso fará com que futuros usuários tenham uma visão incompleta das conversas)
+ Quando minha conta for desativada, apague todas as mensagens que eu enviei (Atenção: isso fará com que futuros usuários tenham uma visão incompleta das conversas)Para continuar, entre com sua senha:Desativar minha conta
@@ -1049,46 +1051,46 @@ Atenção: este arquivo poderá ser apagado se o aplicativo for desinstalado.MotivoVersão %s
- Notificações de Resolução de Problemas
- Diagnóstico de Resolução de Problemas
+ Resolver problemas nas notificações
+ Diagnóstico de resolução de problemasExecutar TestesExecutando… (%1$d of %2$d)
- Diagnóstico básico está ok. Se você ainda não recebe notificações, por favor relate um erro para nos ajudar a investigar.
+ O diagnóstico básico está ok. Se você ainda não recebe notificações, por favor relate um erro para nos ajudar a investigar.Um ou mais testes falharam, tente as correções sugeridas.Um ou mais testes falharam, por favor relate um erro para nos ajudar a investigar.
- Configurações do sistema.
+ Configurações do sistemaNotificações estão ativadas nas configurações do sistema.Notificações estão desativadas nas configurações do sistema. Por favor, revise as configurações do sistema.Abra as Configurações
- Configurações da Conta.
+ Configurações da contaNotificações estão ativadas para sua conta.Notificações estão desativadas para sua conta.↵
\nPor favor, revise as configurações da conta.Ativar
- Configurações da sessão.
+ Configurações da sessãoNotificações estão ativadas nesta sessão.Remover da salaNotificações não estão ativadas nesta sessão.↵
\nPor favor, revise as configurações do Element.Ativar
- Revisão do Play Services
+ Versão do Google Play ServicesGoogle Play Services APK está disponível e atualizado.Element usa Google Play Services para entregar mensagens push, mas isto não parece está configurado corretamente:
%1$sConsertar Play Services
- Token Firebase
+ Token do FirebaseToken FCM recuperado com sucesso:
%1$sLigar mesmo assimFalha ao recuperar o token do FCM:
%1$s
- Registro de Token
+ Registro do token do FirebaseToken FCM registrado com sucesso no HomeServer.Falha ao registrar o token FCM no HomeServer:
%1$s
@@ -1118,8 +1120,8 @@ Tente reiniciar a aplicação.Prévia de links dentro do chat quando seu homeserver suporta este recurso.Permitir que saibam quando eu estiver digitandoDeixe outros usuários saberem quando você estiver digitando.
- Mostrar confirmações de leitura
- Clique nas notificações de leitura para uma lista detalhada.
+ Mostrar confirmações de leitura dos outros usuários
+ Clique nas confirmações de leitura para obter mais informações.Mostrar eventos de entrada e saída de salaConvites, remoções e banimentos não são afetados.Mostrar eventos da conta
@@ -1132,8 +1134,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Restrições em segundo plano estão ativadas para o Element.↵
\nO aplicativo funciona bastante restringido enquanto está em segundo plano, o que pode afetar as notificações.↵
\n%1$s
- Formatação Markdown
- Fomatar mensagens usando a sintaxe markdown antes delas serem enviadas. Isto permite uma formatação avançada como usar asteriscos para mostrar texto em itálico.
+ Formatação de texto
+ Formatar o texto das mensagens a serem enviadas. Por exemplo: inserir asteriscos antes e depois do texto, mostrará o texto em itálico.Conceder permissãoOcorreu um erro ao confirmar seu endereço de e-mail.
@@ -1143,14 +1145,14 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Informação adicional: %sInicie a câmera do sistema em vez da câmera personalizada.
- Esta opção requer um aplicativo de terceiros para gravar as mensagens.
+ Esta opção requer um aplicativo de terceiros para gravar mensagens de voz.O comando \"%s\" precisa de mais parâmetros ou alguns parâmetros estão incorretos.
- Markdown foi ativado.
- Markdown foi desativado.
+ A formatação de texto foi ativada.
+ A formatação de texto foi desativada.
- Aumente o desempenho apenas carregando os membros da sala na primeira exibição.
- Seu homeserver não suporta o carregamento Lazy de membros da sala ainda. Tente depois.
+ Aumente o desempenho apenas carregando os participantes da sala na primeira exibição.
+ Seu servidor principal ainda não suporta o carregamento Lazy de participantes da sala. Tente depois.Desculpe, ocorreu um erro
@@ -1171,7 +1173,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Se um usuário deixar um aparelho desconectado por um período de tempo, com a tela desligada, o aparelho entrará no modo Soneca. Isso impede que os aplicativos acessem a rede, adiando seus trabalhos, sincronizações e alarmes padrão.Criar frase secretaA frase secreta está errada
- Carregamento Lazy dos membros das salas
+ Carregamento Lazy dos participantes das salasChamada de vídeo em andamento…
@@ -1197,10 +1199,10 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
AbortarDeseja mesmo sair\?
- Configurações avançadas de notificações
- Importância da notificação por evento
+ Configurar notificações
+ Configurar notificações por evento
- Configurações personalizadas.
+ Configurações personalizadasObserve que alguns tipos de mensagens estão configurados para serem silenciosos (produzirão uma notificação sem som).Algumas notificações estão desativadas nas suas configurações personalizadas.Falha ao carregar regras personalizadas, tente novamente.
@@ -1251,8 +1253,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
ProntoNotificações
- Peça ao administrador do seu servidor principal (%1$s) que configure um servidor TURN para que as chamadas funcionem de maneira confiável.↵
-\n↵
+ Peça ao administrador do seu servidor principal (%1$s) que configure um servidor TURN para que as chamadas funcionem de maneira confiável.
+\n
\nAlternativamente, você pode tentar usar o servidor público em %2$s. No entanto, ele não é tão confiável e compartilhará o seu IP com esse servidor. Você também pode configurar isso nas Configurações.Tente usar %sNão pergunte novamente
@@ -1285,7 +1287,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Chamada em andamento (%s)Retornar à chamada
- Adicionar um servidor de identidade nas suas configurações para executar esta ação.
+ Adicione um servidor de identidade nas suas configurações para executar esta ação.Cancelar conviteReduzir privilégios\?Você não poderá desfazer essa alteração, já que está reduzido seus privilégios. Se você for a última pessoa nesta sala, será impossível recuperar a permissão atual.
@@ -1293,8 +1295,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Bloquear usuário
- Ao bloquear este usuário, as mensagens dele serão ocultadas de você em todas as salas.↵
-\n↵
+ Ao bloquear este usuário, as mensagens dele serão ocultadas de você em todas as salas.
+\n
\nVocê pode reverter esta ação a qualquer momento nas configurações.Desbloquear usuárioDesbloquear este usuário mostrará todas as mensagens dele novamente.
@@ -1302,8 +1304,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Tem certeza que quer cancelar o convite para este usuário\?Remover usuárioMotivo da remoção
- esta ação removerá o usuário desta sala.↵
-\n↵
+ esta ação removerá o usuário desta sala.
+\n
\nPara impedir que o usuário nunca mais entre novamente, você precisará bani-lo.Banir usuárioMotivo do banimento
@@ -1332,9 +1334,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
%s↵
\nA sincronização pode ser adiada dependendo dos recursos (bateria) ou do estado do aparelho (modo de suspensão).Integrações
- Use o Gerenciador de Integrações para gerenciar bots, pontes, widgets e pacotes de figurinhas.↵
-\n
-\nO Gerenciador de Integrações recebe dados de configuração e pode modificar widgets, enviar convites para salas e definir níveis de privilégios em seu nome.
+ Use o Gerenciador de Integrações para gerenciar bots, pontes, widgets e pacotes de figurinhas.
+\nO Gerenciador de Integrações recebe dados de configuração e pode modificar widgets, enviar convites para salas e definir níveis de permissão em seu nome.Botão enter do teclado enviará a mensagem em vez de adicionar uma quebra de linhaBackup Seguro
@@ -1561,8 +1562,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Excluir as chaves de criptografia do servidor\? Você não será mais capaz de usar a sua chave de recuperação para ler o histórico de mensagens criptografadas.Novo Backup da Chave
- Foi detectado um novo backup da chave de mensagem.↵
-\n↵
+ Foi detectado um novo backup da chave de mensagem.
+\n
\nSe você não definiu o novo método de recuperação, um invasor pode estar tentando acessar sua conta. Altere a senha da sua conta e defina um novo método de recuperação imediatamente nas Configurações.Foi eu
@@ -1639,12 +1640,12 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
O compromisso de hash não coincidiuO SAS não correspondeA sessão recebeu uma mensagem inesperada
- Foi recebida uma mensagem inválida
+ Uma mensagem inválida foi recebidaChave incorretaContato não correspondeErro Desconhecido
- Você não está usando nenhum Servidor de Identidade
+ Você não está usando algum servidor de identidadeNenhum servidor de identidade está configurado. É necessário usar um para redefinir sua senha.Parece que você está tentando se conectar com outro servidor local. Deseja sair\?
@@ -1673,10 +1674,10 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Veja as reaçõesReações
- Mensagens excluídas
- Mostrar mensagens excluídas
- Mostrar um espaço reservado para mensagens excluídas
- Evento excluído pelo usuário
+ Mensagem apagada
+ Mostrar mensagens apagadas
+ Mostrar um espaço reservado para mensagens apagadas
+ Evento apagado pelo usuárioEvento moderado pelo administrador da salaÚltima edição por %1$s em %2$s
@@ -1708,8 +1709,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Importar as chaves de arquivo \"%1$s\".
- Versão SDK de Matrix
- Outros avisos de terceiros
+ Versão do SDK da Matrix
+ Outras licenças de terceirosVocê já está vendo esta sala!Reações rápidas
@@ -1722,7 +1723,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Nenhuma regra Push definidaNenhuma entrada Push registrada
- id_do_app:
+ app_id:chave_push:nome_da_ tela_ do_app:nome_da_sessão:
@@ -1741,7 +1742,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Obrigado, a sugestão foi enviada com êxitoA sugestão não foi enviada (%s)
- Mostrar eventos ocultos na linha do tempo
+ Mostrar eventos ocultos nas conversasConversas
@@ -1768,7 +1769,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Nome ou ID (#example:matrix.org)Ativar o recurso de deslizar para responder nas conversas
- Merge não conseguiu decifrar a mensagem na linha do tempo
+ Alertar apenas uma vez em uma conversa de que não é possível descriptografar as mensagens, em vez de alertar para cada mensagemAdicione uma aba dedicada para notificações não lidas na tela principal.Link copiado para a memória
@@ -1794,7 +1795,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Servidor de identidadeDesconectar servidor de identidadeConfigurar servidor de identidade
- Alterar o servidor de identidade
+ Alterar servidor de identidadeAtualmente você está usando %1$s para descobrir e ser descoberto pelos contatos existentes.No momento, você não está usando um servidor de identidade. Para descobrir e ser descoberto pelos contatos existentes, adicione um abaixo.Endereços de e-mail detectáveis
@@ -1817,7 +1818,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Atualmente, você está compartilhando endereços de e-mail ou números de telefone no servidor de identidade %1$s. Você precisará reconectar-se a %2$s para parar de compartilhá-los.Concorde com os Termos de Serviço do servidor de identidade (%s), para que você possa ser descoberto por endereço de e-mail ou por número de telefone.
- Ativar registros detalhados.
+ Ativar registros detalhadosOs registros detalhados ajudarão os desenvolvedores, ao fornecerem mais registros quando você usar sacudir o aparelho. Mesmo quando ativado, o aplicativo não registra o conteúdo da mensagem ou qualquer outro dado privado.
@@ -1857,10 +1858,10 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Não conseguia lidar com dados compartilhadosMÍDIA
- Não há mídia nesta sala
+ Nenhuma mídia nesta salaARQUIVOS%1$s em %2$s
- Não há arquivos nesta sala
+ Nenhum arquivo nesta salaÉ spamÉ inapropriado
@@ -1887,9 +1888,9 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
\n↵
\nPermita o acesso na próxima janela para poder exportar suas chaves manualmente.
- Não há conexão de rede neste momento
+ Não há conexão de rede no momento
- Bloqueia usuário
+ Bloquear usuárioTodas as mensagens novas (com som)Todas as mensagens novas
@@ -1897,7 +1898,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
SilenciarConfiguraçõesAdicionar aos favoritos
- Excluír dos favoritos
+ Remover dos favoritosSair da sala%1$s não fez nenhuma alteraçãoVocê não fez nenhuma alteração
@@ -1905,7 +1906,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Estraga-SurpresaDigite palavras-chave para encontrar uma reação.
- Você não está bloqueando nenhum usuário
+ Nenhum usuário bloqueadoClique longo sobre uma sala para ver mais opções
@@ -1928,7 +1929,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Hospedagem Premium para organizaçõesSaiba maisOutros
- Configurações personalizadas
+ Configurações avançadas e preferênciasContinuarConecte-se a %1$s
@@ -1961,7 +1962,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Um e-mail de confirmação será enviado para sua caixa de entrada, para você confirmar a definição de sua nova senha.PróximoE-mail
- Senha nova
+ Nova senhaAtenção!Alterar a sua senha redefinirá todas as chaves de criptografia de ponta a ponta existentes em todas as suas sessões, tornando o histórico de mensagens criptografadas ilegível. Faça uma cópia (backup) das suas chaves, ou exporte as chaves de outra sessão antes de alterar a sua senha.
@@ -2048,12 +2049,12 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Lida porVocê está desconectada/o
- Isso pode ser devido à vários motivos:↵
-\n↵
-\n• Você alterou sua senha em outra sessão.↵
-\n↵
-\n• Você excluiu esta sessão de outra sessão.↵
-\n↵
+ Isso pode ser devido à vários motivos:
+\n
+\n• Você alterou sua senha em outra sessão.
+\n
+\n• Você excluiu esta sessão de outra sessão.
+\n
\n• O administrador do seu servidor invalidou seu acesso por motivos de segurança.Entrar novamente
@@ -2086,7 +2087,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Veja todas as minhas sessõesConfigurações avançadasModo desenvolvedor
- O modo desenvolvedor ativa características ocultas e pode também tornar o aplicativo menos estável. Somente para desenvolvedores!
+ O modo de desenvolvedor permite ativar recursos ocultos, o que pode tornar o aplicativo menos estável. Somente para desenvolvedores!Agitar celularDetectar patamarAgite seu telefone para testar o limiar de detecção
@@ -2098,7 +2099,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Mostrando apenas os primeiros resultados, digite mais letras…Relatar imediatamente as falhas
- Element pode quebrar com mais freqüência quando ocorre um erro inesperado
+ Element poderá quebrar com mais frequência quando ocorrer um erro inesperadoAdicionar ¯\\_(ツ)_/¯ para uma mensagem de texto simples
@@ -2159,9 +2160,9 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
\n↵
\nPara máxima segurança, faça isso pessoalmente.As mensagens nesta sala não estão criptografadas de ponta a ponta.
- As mensagens nesta sala são criptografadas de ponta a ponta.↵
-\n↵
-\nSuas mensagens são protegidas com cadeados e somente você e o destinatário têm as chaves exclusivas que permitam a sua leitura.
+ As mensagens nesta sala estão criptografadas de ponta a ponta.
+\n
+\nSuas mensagens estão protegidas com cadeados e somente você e o destinatário têm as chaves exclusivas que permitem a leitura delas.SegurançaSaiba maisMais
@@ -2172,8 +2173,8 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Uma pessoa%1$d pessoas
- Subidas
- Deixar a sala
+ Mídia e arquivos
+ Sair da salaDeixando a sala…Administradores
@@ -2204,9 +2205,9 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Envia a mensagem colorida como arco-írisEnvia o emoji colorido como um arco-íris
- Linha do Tempo
+ Conversas
- Editor de mensagens
+ Campo de textoAtivar a criptografia de ponta a pontaUma vez ativada, a criptografia não poderá ser desativada.
@@ -2224,12 +2225,12 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Sua nova sessão agora está confirmada. Ela tem acesso às suas mensagens criptografadas, e outros usuários a verão como confirmada.Autoverificação
- A autoverificação está ativada↵
+ A autoverificação está ativada
\nChaves privadas estão no aparelho.
- A autoverificação está ativada↵
-\nAs chaves são confiáveis.↵
+ A autoverificação está ativada
+\nAs chaves são confiáveis.
\nAs chaves privadas não são conhecidas
- A autoverificação está ativada.↵
+ A autoverificação está ativada.
\nAs chaves não são confiáveisA autoverificação não está ativada
@@ -2304,11 +2305,11 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Atenção:Você só deveria entrar no armazenamento secreto a partir de um aparelho confiável
- Excluír…
+ ApagarDeseja enviar este anexo para %1$s\?
- Enviar imagem do tamanho original
- Enviar imagens do tamanho original
+ Enviar imagem no tamanho original
+ Enviar imagens no tamanho originalConfirmar a exclusão
@@ -2316,7 +2317,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Incluir o motivoMotivo da edição
- Evento excluído pelo usuário, motivo: %1$s
+ Evento apagado pelo usuário, motivo: %1$sEvento moderado pelo administrador da sala, motivo: %1$sAs chaves já estão atualizadas!
@@ -2402,7 +2403,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Configuração de notificaçõesSolução de problemas
- Mensagem…
+ Digite uma mensagem…Use Arquivo
@@ -2411,7 +2412,6 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Verificando a chave de backupCriando uma Frase Secreta de Recuperação permite proteger e desbloquear mensagens criptografadas e estabelecer confiança.
\n
-\n
\nSe você não quiser definir uma Senha de Mensagem, crie antes uma Chave de Mensagem.Criar uma Frase Secreta de Recuperação permite proteger e desbloquear mensagens criptografadas e estabelecer confiança.Se você cancelar agora, poderá perder mensagens e dados criptografados para sempre se esquecer seus credenciais.
@@ -2429,12 +2429,12 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Falha na importação de chavesMensagens contendo @room
- Mensagens criptografadas em bate-papos individuais
- Mensagens criptografadas em conversas em grupo
- Quando as salas são atualizadas
- Definir a importância da notificação por evento
+ Mensagens criptografadas em conversas individuais
+ Mensagens criptografadas em salas
+ Quando a versão da sala é atualizada
+ Ajustar as notificações por evento
- Envia uma mensagem como texto simples, sem interpretá-la como markdown
+ Envia uma mensagem como texto simples, sem formatar o textoNome de usuário e/ou senha incorretos. A senha digitada começa ou termina com espaços, favor verificá-la.Esta conta foi desativada.
@@ -2460,7 +2460,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Não conheça sua Frase Secreta de Chave do Backup, você pode %s.Chave de recuperação de Chave do Backup
- Impedir captura da tela do aplicativo
+ Impedir a captura de tela do aplicativoAtivando esta opção acrescenta FLAG_SECURE a todas as atividades. Reinicie o aplicativo para que a alteração tenha efeito.Arquivo de mídia adicionado à Galeria
@@ -2504,7 +2504,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Não foi possível criar sua DM. Por favor, verifique os usuários que você deseja convidar e tente novamente.
- Adicionar membros
+ Adicionar participantesCONVITEConvidando os usuários…Convidar Usuários
@@ -2521,7 +2521,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Carregando os idiomas disponíveis…Abra termos de %s
- Desconectar do servidor de identidade %s\?
+ Desconectar-se do servidor de identidade %s\?Este servidor de identidade está desatualizado. Element suporta apenas API V2.Esta operação não é possível. O servidor doméstico está desatualizado.Por favor, primeiro configure um servidor de identidade.
@@ -2534,7 +2534,7 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Use %1$sComo alternativa, você pode digitar o endereço de outro servidor de identidadeDigite o endereço de um servidor de identidade
- Submeter
+ EnviarDefinir o papelPapelBate-papo aberto
@@ -2616,4 +2616,34 @@ Na próxima tela, você será solicitado a permitir que o Element funcione sempr
Confirme o PIN para desativar o PINEvitar chamadas acidentaisConfirmarei a intenção de iniciar uma chamada
+ Você não tem permissão para iniciar uma chamada em grupo nesta sala
+ Uma chamada em grupo já está em andamento!
+ Iniciar chamada de vídeo
+ Iniciar chamada de voz
+ As chamadas utilizam as políticas de segurança e permissão do Jitsi. Todas as pessoas que estão atualmente na sala verão um convite para participar enquanto sua chamada estiver acontecendo.
+ Você não pode iniciar uma chamada com você mesmo
+ Você não pode iniciar uma chamada consigo mesmo. Aguarde os participantes aceitarem o convite
+ Falha ao adicionar o widget
+ Falha ao remover o widget
+
+ %1$d/%2$d chave importada com êxito.
+ %1$d/%2$d chaves importadas com êxito.
+
+
+ Gerenciar integrações
+ Nenhum widget ativo
+ A sala foi criada, mas alguns convites não foram enviados pelo seguinte motivo:
+\n
+\n%s
+
+
+ %1$s, %2$s e %3$d outro leu
+ %1$s, %2$s e %3$d outros leram
+
+
+ Código errado, %d tentativa restante
+ Código errado, %d tentativas restantes
+
+ Atenção! Última tentativa restante antes de você ser desconectada/o!
+ Muitos erros, você foi desconectada/o
diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml
index 72291bdb04..42d96669cb 100644
--- a/vector/src/main/res/values-ru/strings.xml
+++ b/vector/src/main/res/values-ru/strings.xml
@@ -12,6 +12,10 @@
Информация о собеседникеИсторические
+ Принять
+ Отклонить
+ Завершить звонок
+
OKОтмена
@@ -611,7 +615,7 @@
Информация о сессии отправителяПубличное имяПубличное имя
- ID
+ ID сессииКлюч сессииПроверкаEd25519 отпечаток
@@ -1592,7 +1596,7 @@
Регистрационный токен
- Сделайте предложение
+ Оставить отзывПожалуйста, напишите ваше предложение ниже.Опишите ваше предложение здесьСпасибо, предложение было успешно отправлено
@@ -1774,7 +1778,7 @@
ЗвукГалереяЭто спам
- Заблокировать пользователя
+ Игнорировать пользователяВсе сообщенияТолько при упоминаниях
@@ -1792,7 +1796,7 @@
СтикерПричина жалобы на контентПожаловаться
- Заблокировать пользователя
+ ИГНОРИРОВАТЬ ПОЛЬЗОВАТЕЛЯВсе сообщения (громко)Без звука
@@ -2664,4 +2668,37 @@
Подтвердите PIN-код, чтобы отключить PIN-кодПредотвращение случайных звонковСпрашивать подтверждение перед звонком
+ У вас нет разрешения на запуск конференции в этой комнате
+ Конференция уже идет!
+ Начать видеовстречу
+ Начать аудиовстречу
+ На встречах используются политики безопасности и разрешения Jitsi. Все люди, находящиеся в данный момент в комнате, увидят приглашение присоединиться во время вашей встречи.
+ Вы не можете позвонить самому себе
+ Вы не можете позвонить самому себе, дождитесь, пока участники примут приглашение
+ Не удалось добавить виджет
+ Не удалось удалить виджет
+
+ %1$d/%2$d ключ успешно импортирован.
+ %1$d/%2$d ключа успешно импортированы.
+ %1$d/%2$d ключей успешно импортировано.
+
+
+ Управление интеграциями
+ Нет активных виджетов
+ Комната создана, но некоторые приглашения не отправлены по следующей причине:
+\n
+\n%s
+
+
+ %1$s, %2$s и %3$d читает
+ %1$s, %2$s и %3$d других читают
+ %1$s, %2$s и %3$d других читают
+
+
+ Неверный код, осталась %d попытка
+ Неверный код, осталось %d попытки
+ Неверный код, осталось %d попыток
+
+ Предупреждение! Последняя оставшаяся попытка перед выходом из системы!
+ Слишком много ошибок, вы вышли из системы
diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml
index 13e05110d9..bbb398cbba 100644
--- a/vector/src/main/res/values-sk/strings.xml
+++ b/vector/src/main/res/values-sk/strings.xml
@@ -10,6 +10,10 @@
Prebieha synchronizácia…Spracovanie udalostí
+ Prijať
+ Odmietnuť
+ Zavesiť
+
SprávyMiestnosťNastavenia
@@ -591,7 +595,7 @@ Pozor! Vykonaním tejto akcie reštartujete aplikáciu a opätovné načítanie
Informácie o relácií odosielateľaVerejné menoVerejné meno
- ID
+ ID relácieKľúč relácieOverenieOdtlačok prsta Ed25519
@@ -1251,4 +1255,562 @@ Na ďalšej obrazovke vás systém požiada o povolenie vždy bežať na pozadí
Toto nie je platná adresa Matrix serveruDomovský server je nedostupný na tejto URL adrese, preverte to prosímRelácie
+ Prehrať
+ Pozastaviť
+ Odmietnuť
+
+
+ Nemáte právo začať konferenčný hovor v tejto miestnosti
+ Konferenčný hovor práve prebieha!
+ Začať video schôdzu
+ Začať audio schôdzu
+ Pre schôdze platia bezpečnostné politiky Jitsi. Počas prebiehajúcej schôdze sa všetkým členom v miestnosti bude zobrazovať pozvanie s možnosťou pridať sa k schôdzi.
+ Nemôžete telefonovať samému sebe
+ Nemôžete telefonovať samému sebe, počkajte, kým sa pridajú ďalší účastníci
+ Nepodarilo sa pridať widget
+ Nepodarilo sa odstrániť widget
+ Kopírovať
+ Úspešné
+
+ Oznámenia
+ Element hovor zlyhal
+ Nepodarilo sa uskutočniť spojenie v reálnom čase.
+\nProsím, požiadajte správcu domovského servera, aby správne nastavil server turn na zaistenie čo najspoľahlivejšej prevádzky hovorov.
+
+ Vybrať zvukové zariadenie
+ Slúchadlo telefónu
+ Reproduktor
+ Slúchadlá
+ Bezdrôtové slúchadlá
+ Prepnúť fotoaparát
+ Predný
+ Zadný
+ Vypnúť HD
+ Zapnúť HD
+
+ Chyba SSL: Nie je možné overiť totožnosť protistrany.
+ Chyba SSL.
+ Zabrániť neúmyselnému telefonovaniu
+ Žiadať potvrdenie pred uskutočnením hovoru
+ Povoliť záložný server pre nadviazanie hovoru
+ Ak váš domovský server neponúka adresu servera turn, na nadviazanie hovorov sa použije %s (počas hovoru zdieľate svoju adresu IP)
+ Prebiehajúci hovor (%s)
+ Návrat k hovoru
+
+ Na uskutočnenie tejto akcie si prosím v nastaveniach pridajte server totožností.
+ Zrušiť pozvanie
+ Znížiť vlastnú úroveň moci\?
+ "Túto zmenu nebudete môcť vrátiť späť pretože znižujete vašu vlastnú úroveň moci. Ak ste jediný poverený používateľ v miestnosti, nebudete môcť znovu získať úroveň, akú máte teraz."
+ Znížiť
+
+
+ Ignorovať používateľa
+ Ignorovaním tohoto používateľa odstránite všetky jeho správy vo vašich spoločných miestnostiach.
+\nZvrátiť túto akciu môžete kedykoľvek vo všeobecných nastaveniach.
+ Neignorovať používateľa
+ Zrušením ignorovania si opäť zobrazíte všetky správy od tohoto používateľa.
+ Zrušiť pozvanie
+ Ste si istí, že chcete zrušiť pozvanie tohoto používateľa\?
+ Vykázať používateľa
+ Dôvod vykázania
+ Vykázaním odstránite používateľa z miestnosti.
+\n
+\nAk si želáte, aby sa nemohol vrátiť, mali by ste mu tiež zakázať vstupovať.
+ Zakázať používateľovi vstupovať
+ Dôvod zákazu vstupovať
+ Povoliť používateľovi vstupovať
+ Povolením používateľovi vstupovať zaistíte, aby sa používateľ mohol vrátiť do miestnosti.
+
+ Potvrdiť vaše heslo
+ Toto nie je možné urobiť cez mobilnú aplikáciu Element
+ Je požadované overenie
+
+
+ Režim synchronizácie na pozadí (Experimentálne)
+ Optimalizovaný na využívanie batérie
+ Element sa bude synchronizovať na pozadí s cieľom ušetriť limitované zdroje (batériu).
+\nV závislosti od kapacity prostriedkov zariadenia môže byť synchronizácia odložená operačným systémom na neskôr.
+ Optimalizovaný na používanie v reálnom čase
+ Element sa bude pravideľne synchronizovať na pozadí v presne stanovenom čase (nastaviteľné).
+\nToto ovplyvní využívanie batérie a prenos údajov, v oznamovacej oblasti sa bude neustále zobrazovať upozornenie, že Element spracúva udalosti.
+ Žiadna synchronizácia na pozadí
+ Nebudete dostávať oznámenia o prichádzajúcich správach, keď aplikácia pracuje na pozadí.
+ Nepodarilo sa aktualizovať nastavenia.
+
+
+ Uprednostňovaný interval synchronizácie
+ %s
+\nSynchronizácia môže byť odložená vzávislosti od kapacity zariadenia (batéria a režim spánku).
+ Integrácie
+ Použite správcu integrácií na nastavenie botov, mostov, widgetov a balíčkov s nálepkami.
+\nSprávci integrácií zbierajú údaje konfigurácie, môžu meniť widgety, posielať pozvania vstúpiť do miestnosti a nastavovať úroveň moci vo vašom mene.
+ Bezpečné zálohovanie
+ Spravovať
+ Nastaviť bezpečné zálohovanie
+ Znovu nastaviť bezpečné zálohovanie
+ Nastaviť na tomto zariadení
+ Zabezpečte sa pred stratou šifrovaných správ a údajov zálohovaním šifrovacích kľúčov na domovskom servery.
+ Vygenerovať nový kľúč zabezpečenia alebo opätovne nastaviť dlhé heslo pre existujúce zálohovanie.
+ Týmto nahradíte váš aktuálny kľúč alebo dlhé heslo.
+
+ Zisťovanie
+ Spravovať nastavenia zisťovania.
+ Povoliť integrácie
+ Správca integrácií
+
+ Integrácie sú zakázané
+ Na vykonanie tejto akcie zaškrtnite \'Povoliť integrácie\' v nastaveniach zisťovania.
+
+
+ Zakázať vstupovať %d používateľ
+ Zakázať vstupovať %d používatelia
+ Zakázať vstupovať %d používateľov
+
+
+ Verejný názov (viditeľný pre ľudí, s ktorými komunikujete)
+ Verejný názov relácie je viditeľný všetkým používateľom, s ktorými komunikujete
+ Kľúče exportované úspešne
+
+
+ %1$d z %2$d kľúč úspešne importovaný.
+ %1$d z %2$d kľúčov úspešne importovaných.
+ %1$d z %2$d kľúčov úspešne importovaných.
+
+
+ neznáma ip
+ %1$s: %2$s
+ %1$s: %2$s %3$s
+
+ Zobraziť
+ Aktívne widgety
+
+
+ Widget
+ Načítať Widget
+ Tento widget pridal:
+ Používaním prijímate cookies od a zdieľate údaje s %s:
+ Používaním zdieľate údaje s %s:
+ Nepodarilo sa načítať widget.
+\n%s
+ Znovu načítať widget
+ Otvoriť v prehliadači
+ Odvolať prístup pre mňa
+
+ Vaše zobrazované meno
+ URL vášho obrázka v profile
+ Vaše ID používateľa
+ Váš vzhľad
+ ID widgetu
+ ID miestnosti
+
+
+ Prepáčte, konferenčné hovory Jitsi nie sú podporované na starších zariadeniach (starší systém než Android 5.0)
+ Tento widget žiada o nasledujúce zdroje:
+ Povoliť
+ Zablokovať všetko
+ Používať fotoaparát
+ Používať mikrofón
+ Čítať média chránené systémom DRM
+
+ Nie je nastavený žiadny správca integrácií.
+ Spravovať integrácie
+ Žiadne aktívne widgety
+ Skôr než budete pokračovať, mali by ste prijať podmienky poskytovania tejto služby.
+
+ Nová relácia žiada o šifrovacie kľúče.
+\nNázov relácie: %1$s
+\nPosledné prihlásenie: %2$s
+\nAk ste sa neprihlásili do ďalšej relácie, ignorujte túto žiadosť.
+ Neoverená relácia žiada o šifrovacie kľúče.
+\nNázov relácie: %1$s
+\nNaposledy prihlásená: %2$s
+\nAk ste sa neprihlásili do novej relácie, ignorujte túto žiadosť.
+
+ Overiť
+ Zdieľať
+ Žiadosť o zdieľanie kľúčov
+ Ignorovať
+
+ Prosím, zadajte dlhé heslo
+ Dlhé heslo je príliš slabé
+
+ Prosím, zmažte dlhé heslo, ak si želáte vygenerovať kľúč obnovenia.
+ Nie je dostupná žiadna relácia matrix
+
+ Nikdy nepríďte o šifrované správy
+ Správy v šifrovaných miestnostiach sú zabezpečené E2E šifrov. Ku kľúčom potrebných na ich čítanie máte prístup len vy a ich adresáti.
+\n
+\nBezpečne si zálohujte šifrovacie kľúče, aby ste o tieto správy neprišli.
+ Začať používať zálohovanie kľúčov
+ (Pokročilé)
+ Exportovať kľúče ručne
+
+ Zabezpečte si zálohu dlhým heslom.
+ Zašifrovaná kópia vašich kľúčov bude uložená na domovskom servery. Ochránte si túto zálohu dlhým heslom pre zachovanie maximálnej bezpečnosti.
+\n
+\nPozor! Dlhé heslo by sa nemalo zhodovať s heslom k vášmu matrix účtu.
+ Nastaviť dlhé heslo
+ Vytváranie zálohy
+ Alebo, Zabezpečte si zálohu kľúčom obnovenia, ktorý si niekde naozaj bezpečne uložíte.
+ (Pre pokročilých) Nastaviť kľúč obnovenia
+ Úspešne nastavené!
+ Vaše kľúče sú zálohované.
+ Váš kľúč obnovenia je ako ochranná sieť - Môžete ho použiť na obnovenie prístupu k vašim zašifrovaným správam aj keď zabudnete dlhé heslo.
+\nKľúč obnovenia si uchovajte na veľmi bezpečnom mieste napr. v správcovi hesiel (alebo v trezore)
+ Kľúč obnovenia si uchovajte na veľmi bezpečnom mieste napr. v správcovi hesiel (alebo v trezore)
+ Hotovo
+ Urobil(a) som si kópiu
+ Uložiť kľúč obnovenia
+ Zdieľať
+ Uložiť ako súbor
+ Kľúč obnovenia bol uložený do súboru \'%s\'.
+\n
+\nPozor: Keď odinštalujete aplikáciu Element, môže dôjsť k zmazaniu tohoto súboru.
+ Kľúč obnovenia bol uložený.
+
+ Záloha už existuje na domovskom servery
+ Zdá sa, že ste si už zálohovanie kľúčov nastavili z inej relácie. Chcete ho nahradiť zálohou, ktorú vytvárate teraz\?
+ Nahradiť
+ Zastaviť
+
+ Prosím, urobte si kópiu
+ Zdieľať kľúč obnovenia…
+ Generovanie kľúča obnovenia podľa dlhého hesla, môže to trvať niekoľko sekúnd.
+ Kľúč obnovenia
+ Neočakávaná chyba
+ Zálohovanie spustené
+ Vaše šifrovacie kľúče sú na pozadí zálohované na domovskom servery. Úvodné zálohovanie môže trvať niekoľko minút.
+
+
+ Ste si istí\?
+ Môžete prísť o šifrované správy, ak sa odhlásite, odinštalujete aplikáciu, alebo stratíte toto zariadenie.
+
+ Získavanie verzie zálohy…
+ Použiť dlhé heslo obnovenia a získať tak prístup k histórii šifrovaných správ
+ Použiť kľúč obnovenia
+ Neviete svoje dlhé heslo obnovenia, môžete %s.
+
+ Použiť kľúč obnovenia a získať tak prístup k histórii šifrovaných správ
+ Vložte kľúč obnovenia
+
+ Obnovenie správ
+
+ Stratili ste kľúč obnovenia, v nastaveniach získate nový.
+ Zálohu nie je možné dešifrovať týmto dlhým heslom: prosím uistite sa, že ste zadali správne dlhé heslo obnovenia.
+ Chyba siete: Prosím skontrolujte vaše pripojenie a skúste znovu.
+
+ Obnova zo zálohy:
+ Výpočet kľúča obnovenia…
+ Sťahovanie kľúčov…
+ Import kľúčov…
+ Sprístupniť históriu
+ Prosím, vložte kľúč obnovenia
+ Zálohu nie je možné dešifrovať týmto kľúčom: prosím, uistite sa, že ste vložili správny kľúč obnovenia.
+
+ Záloha obnovená %s !
+
+ Záloha s %d kľúčom obnovená.
+ Záloha s %d kľúčmi obnovená.
+ Záloha s %d kľúčami obnovená.
+
+
+ %d nový kľúč bol pridaný do tejto relácie.
+ %d nové kľúče boli pridané do tejto relácie.
+ %d nových kľúčov bolo pridaných do tejto relácie.
+
+
+ Nepodarilo sa získať poslednú verziu kľúčov na obnovenie (%s).
+ Šifrovanie nie je v tejto relácii aktivované
+
+
+ Obnoviť zo zálohy
+ Vymazať zálohu
+
+ Zálohovanie kľúčov je nastavené správne pre túto reláciu.
+ Zálohovanie kľúčov nie je aktívne v tejto relácii.
+ Kľúče z tejto relácie nie sú zálohované.
+
+ Záloha je podpísaná kľúčom z neznámej relácie, ID %s.
+ Záloha je podpísana platným kľúčom z tejto relácie.
+ Záloha je podpísana platným kľúčom z overenej relácie %s.
+ Záloha je podpísana platným kľúčom z neoverenej relácie %s
+ Záloha je podpísana neplatným kľúčom z overenej relácie %s
+ Záloha je podpísana neplatným kľúčom z neoverenej relácie %s
+ Nepodarilo sa zistiť stav dôverihodnosti zálohy (%s).
+
+ Ak chcete v tejto relácii používať zálohovanie kľúčov, zadajte teraz dlhé heslo alebo kľúč obnovenia.
+ Mazanie zálohy…
+ Nepodarilo sa vymazať zálohu (%s)
+
+ Zisťovanie stavu zálohovania
+ Vymazať zálohu
+ Vymazať zálohované šifrovacie kľúče z domovského servera\? Nebudete môcť viac čítať históriu šifrovaných správ zadaním kľúča obnovenia.
+
+ Nová záloha kľúčov
+ Bola zistená nová bezpečná záloha šifrovacích kľúčov.
+\n
+\nAk ste si nenastavili nový spôsob obnovenia kľúčov, útočník sa môže pokúšať pristupovať k vášmu účtu. V nastaveniach si prosím hneď zmente prihlasovacie heslo účtu a nastavte zálohovanie kľúčov.
+ Bol(a) som to ja
+
+ Nikdy neprídete o šifrované správy
+ Začnite používať zálohovanie kľúčov
+
+ Bezpečné zálohovanie
+ Zabezpečte sa proti strate šifrovaných správ a údajov
+
+ Nikdy neprídete o šifrované správy
+ Použiť kľúče zo zálohy
+
+ Nové bezpečné šifrovacie kľúče
+ Spravovať v zálohovaní kľúčov
+
+ Zálohovanie kľúčov. Môže to trvať niekoľko minút…
+
+
+ Nastavenie bezpečného zálohovania
+
+ Všetky kľúče sú zálohované
+
+ Zálohovanie %d kľúča…
+ Zálohovanie %d kľúčov…
+ Zálohovanie %d kľúčov…
+
+
+ Verzia
+ Algoritmus
+ Podpis
+
+ Neplatná odpoveď pri zisťovaní domovského servera
+ Automaticky doplniť možnosti servera
+ Element zistil vlastné nastavenie servera pre vaše ID používateľa a doménu \"%1$s\":
+\n%2$s
+ Použiť nastavenia
+
+ Boli ste odhlásení, pretože vaše prihlasovacie údaje vypršali alebo nie sú viac platné.
+
+ Overiť porovnaním krátkeho textu.
+ Z dôvodu dodržania maximálnej bezpečnosti odporúčame, aby ste toto urobili osobne alebo použili iný dôveryhodný komunikačný kanál.
+ Spustiť overenie
+ Prichádzajúca žiadosť o overenie
+ Overte túto reláciu, aby ste ju mohli označiť za dôveryhodnú. Dôverovanie reláciám vašich komunikačných partnerov vám pridáva pokoj na duši pri používaní E2E šifrovaných správ.
+ Overením tejto relácie si ju označíte ako dôveryhodnú a tiež označíte vašu reláciu ako dôveryhodnú pre protistranu.
+
+ Overte túto reláciu potvrdením, že na obrazovke protistrany sa zobrazia nasledujúce emoji
+ Overte túto reláciu potvrdením, že na obrazovke protistrany sa zobrazia nasledujúce čísla
+
+ Prijali ste žiadosť o overenie.
+ Zobraziť žiadosť
+ Čakanie na potvrdenie protistrany…
+
+ Overené!
+ Úspešne ste overili túto reláciu.
+ Šifrované správy s týmto používateľom sú zabezpečené E2E šifrou a nik okrem vás ich nemôže čítať.
+ Rozumiem
+
+ Nič sa neobjavuje\? Ešte nie všetci klienti podporujú interaktívne overenie. Použite pôvodný spôsob overenia.
+ Použiť pôvodný spôsob overenia.
+
+ Overenie kľúčov
+ Žiadosť zrušená
+ Protistrana prerušila overenie.
+\n%s
+ Overenie je zrušené.
+\nDôvod: %s
+
+ Interaktívne overenie relácie
+ Žiadosť o overenie
+ %s chce overiť vašu reláciu
+
+ Používateľ prerušil overovanie
+ Čas overenia vypršal
+ Neznáma transakcia relácie
+ Kľúč relácie alebo metóda odtlačku, MAC alebo SAS sa nezhodujú
+ Nesúhlasí použitie dohodnutého odtlačku
+ Nesúhlasí SAS
+ Relácia dostala neočakávanú správu
+ Bola prijatá neplatná správa
+ Nesúhlas kľúčov
+ Nesúhlas používateľov
+ Neznáma chyba
+
+ Nepoužívate žiaden server totožností
+ Nemáte nastavený server totožností, čo znamená, že si nebudete môcť obnoviť zabudnuté heslo účtu.
+
+ Zdá sa, že sa pokúšate pripojiť k inému domovskému serveru. Chcete sa odhlásiť\?
+
+ Upraviť
+ Odpovedať
+
+ Skúsiť znovu
+ Aplikáciu začnite používať tým, že vstúpite do miestnosti.
+ Vám odoslal pozvanie
+ Pozvaný používateľom %s
+
+ Zoznam miestností je prázdny!
+ Nemáte žiadne neprečítané správy
+ Vitajte doma!
+ Tu nájdete neprečítané správy
+ Konverzácie
+ Tu sa zobrazia priame konverzácie
+ Miestnosti
+ Tu sa zobrazia vaše miestnosti
+
+ Reakcie
+ Súhlasím
+ Páči sa mi
+ Pridať reakciu
+ Zobraziť reakcie
+ Reakcie
+
+ Odstránená správa
+ Zobrazovať odstránené správy
+ Namiesto odstránených správ sa zobrazí prázdna položka
+ Udalosť odstránená používateľom
+ Udalosť moderovaná správcom
+ Naposledy upravil %1$s %2$s
+
+
+ Nesprávne vytvorená udalosť, nie je možné zobraziť
+ Vytvoriť novú miestnosť
+ Žiadna sieť. Prosím skontrolujte pripojenie na internet.
+ Zmeniť
+ Zmeniť sieť
+ Prosím čakajte…
+ Všetky komunity
+
+ Nie je možné zobraziť náhľad tejto miestnosti
+ Nazeranie do verejných miestností nie je zatiaľ podporované
+
+ Miestnosti
+ Priame konverzácie
+
+ Nová miestnosť
+ VYTVORIŤ
+ Názov miestnosti
+ Verejná
+ Ktokoľvek môže vstúpiť do tejto miestnosti
+ Adresár miestností
+ Uverejniť túto miestnosť v adresáry miestností
+ Miestnosť bola vytvorená, ale niektoré pozvania neboli odoslané z dôvodu:
+\n
+\n%s
+
+ Pri získavaní stavu dôveryhodnosti nastala chyba
+ Pri získavaní údajov o zálohe kľúčov nastala chyba
+
+ Importovať E2E kľúče zo súboru \"%1$s\".
+
+ Verzia Matrix SDK
+ Ďalšie poznámky tretích strán
+ Už máte túto miestnosť zobrazenú!
+
+ Rýchle reakcie
+
+ Všeobecné
+ Predvoľby
+ Bezpečnosť a súkromie
+ Expertné
+ Pravidlá push oznámení
+ Nedefinované žiadne pravidlá push
+ Nezaregistrované žiadne brány push
+
+ ID aplikácie:
+ Kľúč push:
+ Zobrazovaný názov aplikácie:
+ Názov relácie:
+ Url:
+ Formát:
+
+ Hlas a video
+ Pomoc a o aplikácii
+
+
+ Zaregistrovať token
+
+ Poslať návrh
+ Nižšie napíšte obsah návrhu.
+ Popíšte váš návrh
+ Ďakujeme, váš návrh bol úspešne odoslaný
+ Návrh sa nepodarilo odoslať (%s)
+
+ Zobrazovať skryté udalosti na časovej osy
+
+ Priame konverzácie
+
+ Čakanie…
+ Šifrovanie náhľadu…
+ Odosielanie náhľadu (%1$s / %2$s)
+ Šifrovanie súboru…
+ Odosielanie súboru (%1$s / %2$s)
+
+ Sťahovanie súboru %1$s…
+ Súbor %1$s bol stiahnutý!
+
+ (Upravené)
+
+ Úpravy správy
+ Neboli nájdené žiadne úpravy
+
+ Filtrovať konverzácie…
+ Nemôžete nájsť, čo hľadáte\?
+ Vytvoriť novú miestnosť
+ Poslať priamu správu
+ Zobraziť adresár miestností
+
+ Názov alebo ID (#priklad:matrix.org)
+
+ Povoliť odpovedať švihnutím na časovej osy
+ Zlúčiť správy nepodarilo sa dešifrovať na časovej osy
+ Zobrazovať záložku oznámenia na hlavnej obrazovke.
+
+ Odkaz skopírovaný do schránky
+
+ Pridať matrix ID
+ Vytváranie miestnosti…
+ Nenájdený žiadny výsledok, ak chcete hľadať na servery, klepnite na pridať Matrix ID.
+ Výsledky uvidíte hneď, čo začnete písať
+ Filtrovať zadaním používateľskeho mena alebo ID…
+
+ Vstupovanie do miestnosti…
+
+ Zobraziť históriu úprav
+
+ Podmienky poskytovania služby
+ Prečítať podmienky
+ Umožnite ostatným vás nájsť
+ Používajte botov, mosty, widgety a balíčky s nálepkami
+
+ Prečítajte si na adrese
+
+
+ Server totožností
+ Odpojiť server totožností
+ Nastaviť server totožností
+ Zmeniť server totožností
+ Používate server totožností %1$s, aby vás ľudia, ktorých poznáte mohli nájsť a aby ste vy mohli vyhľadávať kontakty.
+ Momentálne nepoužívate server totožností. Nižšie si ho môžete nastaviť, ak chcete vašim známym umožniť, aby vás mohli nájsť a ak aj vy chcete vyhľadávať kontakty.
+ Emailové adresy, podľa ktorých je vás možné nájsť
+ Možnosti zisťovania sa zobrazia, až keď pridáte emailovú adresu.
+ Možnosti zisťovania sa zobrazia, až keď pridáte telefónne číslo.
+ Odpojením sa od servera totožností znemožníte ostatným, aby vás našli a tiež nebudete môcť kontakty pozývať zadaním emailovej adresy alebo telefónneho čísla.
+ Telefónne čísla, podľa ktorých je vás možné nájsť
+ Poslali sme vám potvrdzujúcu správu na adresu %s, skontrolujte si email a overte vašu emailovú adresu klepnutím na odkaz, ktorý obsahuje
+ Na adresu %s sme vám odoslali potvrdzujúcu správu, aby ste mohli pokračovať, skontrolujte si email a klepnite na odkaz, ktorý sme vám poslali
+ Očakáva sa
+
+ Zadajte URL adresu servera totožností
+ Nie je možné sa pripojiť k serveru totožností
+ Prosím, zadajte URL adresu servera totožností
+ Server totožností nezverejnil podmienky poskytovania služieb
+ Vami vybratý server totožností nezverejňuje podmienky používania služieb. Pokračujte len v prípade, že dôverujete vlastníkovi servera
+ Na číslo %s bola odoslaná textová správa. Prosím zadajte overovací kód, ktorý obsahuje.
+ Overovací kód nie je správny.
+
+ Emailové adresy a telefónne čísla zdieľate cez server totožností %1$s. Ak chcete toto zdieľanie zastaviť, mali by ste sa znovu pripojiť k serveru %2$s.
+ Odsúhlaste podmienky používania služieb servera totožností (%s), aby vás ostatní mohli nájsť podľa emailovej adresy alebo telefónneho čísla.
+
+ Povoliť podrobné záznamy.
+ Podrobné záznamy pomôžu vývojárom poskytnúť viac detailov, keď posielate hlásenie o chybe. Aj keď je toto zapnuté, aplikácia nezaznamenáva obsah správ ani žiadne iné súkromné údaje.
+
+
diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml
index f1ffb2079a..5383c03ba9 100644
--- a/vector/src/main/res/values-sv/strings.xml
+++ b/vector/src/main/res/values-sv/strings.xml
@@ -22,9 +22,9 @@
HistoriskBuggrapportGemenskapsdetaljer
- Skicka ett klistermärke
+ Skicka en dekalSäkerhetskopiering av nycklar
- Använd säkerhetskopiering av nycklar
+ Använd nyckelsäkerhetskopieringVerifiera sessionSäkerhetskopiering av nycklar är inte färdig, vänligen vänta…
@@ -33,7 +33,7 @@
Säker säkerhetskopiering av nycklar bör vara aktivt i alla dina sessioner för att förhindra att du förlorar åtkomst till dina krypterade meddelanden.Jag vill inte ha mina krypterade meddelandenSäkerhetskopierar nycklar…
- Använd säkerhetskopiering av nycklar
+ Använd nyckelsäkerhetskopieringÄr du säker\?SäkerhetskopieraDu kommer att förlora åtkomst till dina krypterade meddelanden om du inte säkerhetskopierar dina nycklar innan du loggar ut.
@@ -140,7 +140,7 @@
RumRumskatalogInga rum
- Inga publika rum tillgängliga
+ Inga offentliga rum tillgängliga1 användare%d användare
@@ -195,13 +195,13 @@
Fråga mig inte igenSkicka filer
- Skicka klistermärke
+ Skicka dekalTa foto eller videoTa ett fotoTa en video
- Du har för närvarande inga klistermärkespaket aktiva.
-\n
+ Du har för närvarande inga dekalpaket aktiva.
+\n
\nLägg till några nu\?fortsätt med…
@@ -288,7 +288,7 @@
Förfrågan har skickatsVänligen öppna Element på en annan enhet som kan dekryptera meddelandet så att den kan skicka nycklarna till den här sessionen.
- Läskvittolista
+ LäsindikationslistaGrupplista
@@ -341,21 +341,21 @@
Kan inte spela in videoInformation
- Element behöver tillstånd att komma åt ditt foto- och videobibliotek för att skicka och spara bilagor.
-\n
-\nVänligen tillåt åtkomst i nästa pop-up för att kunna skicka filer från din telefon.
+ Element behöver tillstånd att komma åt ditt foto- och videobibliotek för att skicka och spara bilagor.
+\n
+\nVänligen ge tillstånd i nästa popup för att kunna skicka filer från din telefon.Element behöver tillstånd att komma åt din kamera för att kunna ta bilder och hålla videosamtal."
\n
-\nVänligen ge tillgång i nästa pop-up för att kunna utföra samtalet."
+\nVänligen ge tillstånd i nästa popup för att kunna utföra samtalet."Element behöver tillstånd att komma åt din mikrofon för hålla röstsamtal."
\n
-\nVänligen ge tillgång i nästa pop-up för att kunna utföra samtalet."
- Element behöver tillstånd att komma åt din kamera och mikrofon för att kunna utföra videosamtal.
-\n
-\nVänligen ge tillgång i nästa pop-up för att kunna utföra samtalet.
- Element kan kolla i din adressbok för att hitta andra Matrixanvändare baserat på deras e-postadresser och telefonnummer. Om du går med på att dela din adressbok för detta ändamål, vänligen ge tillgång i nästa pop-up.
+\nVänligen ge tillstånd i nästa popup för att kunna utföra samtalet."
+ Element behöver tillstånd att komma åt din kamera och mikrofon för att kunna utföra videosamtal.
+\n
+\nVänligen ge tillstånd i nästa popup för att kunna utföra samtalet.
+ Element kan kolla i din adressbok för att hitta andra Matrixanvändare baserat på deras e-postadresser och telefonnummer. Om du går med på att dela din adressbok för detta ändamål, vänligen ge tillstånd i nästa popup.Element kan kolla i din adressbok för att hitta andra Matrixanvändare baserat på deras e-postadresser och telefonnummer.
\n
\nVill du dela din adressbok för detta ändamål\?
@@ -435,11 +435,11 @@
Ta bort från det här rummetBannaAvbanna
- Kasta ut
+ KickaÅterställ till vanlig användareGör till moderatorGör till administratör
- Dölj alla meddelanden från den här användaren
+ IgnoreraFiltrera rumsmedlemmarRUMRUM
@@ -458,7 +458,7 @@
%s försökte ladda en specifik punkt i det här rummets tidslinje, men kunde inte hitta den.
- Skriv en hemserver att visa listan över publika rum från
+ Skriv en hemserver att visa listan över offentliga rum frånAlla rum på %s-servernAlla %s-rum på Matrix
@@ -566,7 +566,7 @@
Du kommer inte att verifiera %1$s (%2$s) om du avbryter nu. Börja igen i hens användarprofil.Meddelanden i det här rummet är totalsträckskrypterade. Lär dig mer och verifiera användare i deras profiler.
- Visa alla meddelanden från den här användaren
+ AvignoreraÄr du säker på att du vill bjuda in %s till den här chatten\?Bjud in med IDBjud in användare med ID
@@ -646,7 +646,7 @@
Meddelanden innehållande mitt användarnamnMeddelanden i direktchattarMeddelanden i gruppchattar
- Element kommer att synka I bakgrunden periodiskt vid precisa tider (konfigurerbart).
+ Element kommer att synka i bakgrunden periodiskt vid precisa tider (konfigurerbart).
\nDetta kommer att påverka data- och batterianvändning, och det kommer att visas en permanent avisering som säger att Element lyssnar efter händelser.Versionolm-version
@@ -660,7 +660,7 @@
AviseringsmålSkicka \"skriver\"-statusarFormatera meddelanden med Markdown-syntax innan de skickas. Detta tillåter avancerad formatering som att använda asterisker för att visa kursiv text.
- Visa tidpunkt för alla meddelanden
+ Visa tidsstämplar för alla meddelandenVisa när folk går med och lämnarFörhandsgranska media innan den skickasInaktivera konto
@@ -742,7 +742,7 @@
Ogiltigt hemserversvarDu har blivit utloggad på grund av ogiltiga eller utgångna uppgifter.
- Verifiera den här sessionen för att markera den som pålitligt. Att lita på folks sessioner ger dig extra sinnesro när du skickar totalsträckskrypterade meddelanden.
+ Verifiera den här sessionen för att markera den som betrodd. Att lita på folks sessioner ger dig extra sinnesro när du skickar totalsträckskrypterade meddelanden.Säkra meddelanden mellan dig och den här användaren är totalsträckskrypterade och kommer inte att vara läsbara för tredje parter.Du använder ingen identitetsserver
@@ -774,7 +774,7 @@
Du delar för närvarande e-postadresser och telefonnummer på hemservern %1$s. Du kommer behöva återansluta till %2$s för att sluta dela dem.Acceptera identitetsserverns (%s) användarvillkor för att låta dig själv vara upptäckbar med e-postadress eller telefonnummer.
- Mångord loggar kommer att hjälpa utvecklare genom att skicka mer loggar när du skickar en raseriskakning. Även när det är aktiverat, så loggar appen inga meddelandeinnehåll eller annan privat data.
+ Mångordiga loggar kommer att hjälpa utvecklare genom att skicka mer loggar när du skickar en raseriskakning. Även när det är aktiverat, så loggar appen inga meddelandeinnehåll eller annan privat data.Visa lösenord
@@ -829,8 +829,8 @@
Sätt ett telefonnummer som valfritt kan användas för att vara upptäckbar av folk som känner dig.Användarnamn eller e-postadressVänligen kolla din e-post
- Vi skickade just ett e-brev till %1$s.
-\nKlicka på länken i det för att fortsätta med kontoskapningen.
+ Vi skickade just ett e-brev till %1$s.
+\nKlicka på länken i det för att fortsätta med kontoskapandet.Den här hemservern kör en för gammal version för att ansluta till. Be administratören för hemservern att uppdatera.Logga in för att återfå krypteringsnycklar som endast lagras på den här enheten. Du behöver dem för att läsa alla dina säkra meddelanden på andra enheter.
@@ -869,10 +869,10 @@
Efter aktivering så kan kryptering inte avaktiveras. Meddelanden som skickas i ett krypterat rum kan inte läsas av servern, bara av deltagarna i rummet. Att aktivera kryptering kan kan göra att många bottar och bryggor inte funkar ordentligt.Meddelanden mellan dig och den här användaren är totalsträckskrypterade och kan inte läsas av tredje parter.
- Din nya session är nu verifierad. Den har tillgång till dina krypterade meddelanden, och andra användare kommer att se den som pålitlig.
+ Din nya session är nu verifierad. Den har tillgång till dina krypterade meddelanden, och andra användare kommer att se den som betrodd.
- Verifiera den här sessionen gör att markera den som pålitlig och ge den tillgång till dina krypterade meddelanden. Om det inte var du som loggade in i den här sessionen så kan ditt konto vara kapat:
+ Verifiera den här sessionen gör att markera den som betrodd och ge den tillgång till dina krypterade meddelanden. Om det inte var du som loggade in i den här sessionen så kan ditt konto vara kapat:Använd en existerande session för att verifiera den här och ge den tillgång till krypterade meddelanden.
@@ -956,7 +956,7 @@
%d nya meddelanden
- Certifikatet har ändrats från en pålitligt till en som vi inte litar på. Servern kan ha förnyat sitt certifikat. Kontakta serveradministratören för det förväntade fingeravtrycket.
+ Certifikatet har ändrats från ett betrott till ett som inte är betrott. Servern kan ha förnyat sitt certifikat. Kontakta serveradministratören för det förväntade fingeravtrycket.InställningarInställningarSysteminställningar.
@@ -969,8 +969,8 @@
NormalIntegrationer
- Använd en integrationshanterare för att hantera bottar, bryggor, widgets och klistermärkespaket.
-\nIntegrationshanterare får konfigurationsdata, och kan ändra widgets, skicka rumsinbjudningar, och ändra användarnivåer å dina vägnar.
+ Använd en integrationshanterare för att hantera bottar, bryggor, widgets och dekalpaket.
+\nIntegrationshanterare får konfigurationsdata, och kan ändra widgets, skicka rumsinbjudningar, och ändra behörighetsnivåer å dina vägnar.Skicka meddelande med returReturtangenten på mjukvarutangentbordet kommer att skicka ett meddelande istället för att lägga till ett radslut
@@ -1050,7 +1050,7 @@
Sammanfogaren misslyckades med att avkryptera ett meddelande i tidslinjenLägg till med Matrix-IDInga resultat hittade, använd \"Lägg till med Matrix-ID\" för att söka på servern.
- Använd bottar, bryggor, widgets och klistermärkespaket
+ Använd bottar, bryggor, widgets och dekalpaketEtt textmeddelande har skickats till %s. Vänligen skriv in verifieringskoden det innehåller.Filen \'%1$s\' (%2$s) är för stor för att laddas upp. Gränsen är %3$s.
@@ -1060,14 +1060,14 @@
KameraLjudGalleri
- Klistermärke
+ DekalSkickar det valda meddelandet som en spoilerGå med miljontals användare gratis på den största publika servernLägger till ¯\\_(ツ)_/¯ till början av ett textmeddelandeLjudFil
- Klistermärke
+ DekalElement hanterar inte meddelanden av typen \'%1$s\'Skickar det valda meddelandet I regnbågsfärger
@@ -1101,8 +1101,1435 @@
Väntar på det här meddelandet, det här kan ta ett tagVid totalsträckskryptering så kan du behöva vänta på att någons meddelande ska komma för att krypteringsnycklarna inte har skickats till dig.Du kan inte komma åt det här meddelandet för att du har blockerats av avsändaren
- Du kan inte komma åt det här meddelandet för att avsändaren inte litar på din session
+ Du kan inte komma åt det här meddelandet för att din session inte är betrodd av avsändarenDu kan inte komma åt det här meddelandet för att avsändaren avsiktligt inte skickade nycklarnaSök i mina kontakterDin kontaktbok är tom
+ Du har inte behörighet att starta ett gruppsamtal i det här rummet
+ Ett gruppsamtal pågår redan!
+ Starta videomöte
+ Starta ljudmöte
+ Möten använder Jitsis säkerhets- och behörighetsprinciper. Alla personer nu i rummet kommer att se en inbjudan för att gå med medans mötet pågår.
+ Du kan inte ringa ett samtal till dig själv
+ Du kan inte ringa ett samtal till dig själv, vänta tills deltagare accepterar inbjudan
+ Misslyckades att lägga till widget
+ Misslyckades att ta bort widget
+ Elementsamtal misslyckades
+ Misslyckades att upprätta en realtidsuppkoppling.
+\nVänligen be administratören för din hemserver att konfigurera en TURN-server för att samtal ska fungera pålitligt.
+
+ Välj ljudenhet
+ Telefon
+ Högtalare
+ Hörlurar
+ Trådlösa hörlurar
+ Fram
+ Bak
+ Stäng av HD
+ Sätt på HD
+
+ SSL-fel: andra partens identitet har inte verifierats.
+ SSL-fel.
+ Förhindra oavsiktligt samtal
+ Fråga efter bekräftelse innan ett samtal startas
+ Aktivt samtal (%s)
+ Återgå till samtal
+
+ Avbryt inbjudan
+ Omnämn
+ Visa sessionslista
+ Du kommer inte kunna ångra den här ändringen eftersom du befordrar användaren till samma behörighetsnivå som dig själv.
+\nÄr du säker\?
+
+ Degradera dig själv\?
+ Du kommer inte kunna ångra den här ändringen eftersom du degraderar dig själv. Om du är den sista privilegierade användaren i det här rummet så kommer det att vara omöjligt att återfå privilegier.
+ Degradera
+
+
+ Ignorera användare
+ Avignorera användare
+ Att avignorera den här användaren kommer att visa alla meddelanden från hen igen.
+ Avbryt inbjudan
+ Är du säker på att du vill avbryta inbjudan för den här användaren\?
+ Kicka användaren
+ Anledning för kick
+ att sparka ut användaren kommer att ta bort hen från det här rummet.
+\n
+\nFör att hindra hen från att gå med i rummet igen så bör du banna hen istället.
+ Banna användaren
+ Anledning för bann
+ Avbanna användaren
+ Att banna användaren kommer att kicka hen från det här rummet och hindra hen från att gå med igen.
+ Att avbanna användaren kommer att låta hen gå med i rummet igen.
+
+ Anledning
+
+ "%1$s, "
+ %1$s och %2$s
+ %1$s %2$s
+
+ LOKALA KONTAKTER (%d)
+ ANVÄNDARKATALOG (%s)
+ Endast Matrixanvändare
+
+ Sök
+ %s skriver…
+ %1$s och %2$s skriver…
+ %1$s, %2$s och andra skriver…
+ Skicka ett krypterat svar…
+ Skicka ett svar (okrypterat)…
+ Anslutningen till servern har tappats.
+ Meddelanden skickades inte. %1$s eller %2$s nu\?
+ Meddelanden skickades inte eftersom en okänd session närvarar. %1$s eller %2$s nu\?
+ Skicka alla igen
+ Avbryt alla
+ Skicka oskickade meddelanden igen
+ Radera oskickade meddelanden
+ Du har inte behörighet att skriva i det här rummet
+ Betro
+ Betro inte
+ Logga ut
+ Ignorera
+ Fingeravtryck (%s):
+ Detta kan betyda att någon med uppsåt fångar upp din trafik, eller att din mobil inte litar på certifikatet som skickades av servern.
+ Om serveradministratören har sagt att detta är förväntat, försäkra att fingeravtrycket nedan matchar fingeravtrycket de angav.
+ Certifikatet har ändrats från ett som var betrott av din mobil. Detta är HÖGST OVANLIGT. Du rekommenderas att INTE ACCEPTERA det nya certifikatet.
+ Acceptera endast certifikatet om serveradministratören har publicerat ett fingeravtryck som matchar det ovan.
+
+
+ 1 valt
+ %d valda
+
+ INBJUDNA
+ ANSLUTNA
+
+ Anledning för att rapportera det här innehållet
+ Avbryt uppladdning
+ Avbryt nedladdning
+
+ Sök
+ Inga resultat
+ MEDDELANDEN
+ GÅ MED
+ KATALOG
+ FAVORITER
+ LÅG PRIORITET
+ INBJUDNINGAR
+ Starta chatt
+ Skapa rum
+ Gå med i rum
+ Gå med i ett rum
+ Skriv ett rums-ID eller ett rumsalias
+
+ Bläddra i katalogen
+ Söker i katalog…
+
+ Favorit
+ Nedprioritera
+ Glöm
+ Lägg till en genväg på hemskärmen
+
+ Meddelanden
+ Användarvillkor
+ Meddelanden från tredje part
+ Upphovsrätt
+ Integritetspolicy
+
+ Telefon
+ Du kan inte göra detta från element på mobilen
+ Autentisering krävs
+
+
+ Diagnostik för felsökning
+ Kör tester
+ Kör… (%1$d av %2$d)
+ Sätt på
+
+ Sätt på
+
+ Misslyckades att ladda anpassade regler, vänligen försök igen.
+ Kolla Play-tjänster
+ APK:n Google Play-tjänster är tillgänglig och uppdaterad.
+ Element använder Google Play-tjänster för att skicka pushmeddelanden, men den verkar inte vara korrekt konfigurerad:
+\n%1$s
+ Fixa Play-tjänster
+
+ Firebase-token
+ FCM-token hämtades framgångsrikt:
+\n%1$s
+ Misslyckades att hämta FCM-token:
+\n%1$s
+ [%1$s]
+\nDet här felet är ur Elements kontroll, och enligt Google indikerar det här felet att den här enheten har för många appar registrerade med FCM. Felet händer endast i fall då extremt många appar är installerade, så det bör inte påverka normala användare.
+ [%1$s]
+\nDet här felet är ur Elements kontroll. Det kan hända av flera anledningar. Det kanske funkar om du försöker igen senare, du kan kolla så att Google Play-tjänster inte är databegränsad i systeminställningarna, eller att enhetens klocka går rätt, eller så kan det hända på en alternativ ROM.
+ [%1$s]
+\nDet här felet är ur Elements kontroll. Det finns inget Google-konto på telefonen. Vänligen öppna kontohanteraren och lägg till ett Google-konto.
+ Lägg till konto
+
+ Token-registrering
+ FCM-token registrerades framgångsrikt på hemservern.
+ Misslyckades att registrera FCM-token på hemservern:
+\n%1$s
+
+ Starta tjänst
+
+ Tjänsten dödades och startades om automatiskt.
+ Tjänsten misslyckades att starta om
+
+ Starta vid boot
+ Tjänsten kommer att startas när enheten startas om.
+ Aktivera start på boot
+
+ Kolla bakgrundsrestriktioner
+ Bakgrundsrestriktioner är inaktiverade för Element. Detta test bör köras med mobildata (inte Wi-Fi).
+\n%1$s
+ Inaktivera restriktioner
+
+ Batterioptimering
+ Element påverkas inte av batterioptimering.
+ Ignorera optimering
+
+ Reducerad sekretess
+ Den här appen behöver behörighet att köra i bakgrunden
+ Apparna behöver inte ansluta till hemservern i bakgrunden, det bör reducera batterianvändning
+ Tänd skärmen i 3 sekunder
+ Bakgrundssynkronisering
+ Bakgrundssynkläge (experimentellt)
+ Optimerad för batteri
+ Användarvillkor
+ Meddelanden från tredje part
+ Upphovsrätt
+ Integritetspolicy
+ Annat
+ Kryptografi
+ Hantering av kryptografiska nycklar
+ Sessioner
+ Låt andra användare se när du skriver.
+ Markdownformatering
+ Visa läsindikationer
+ Tryck på läsindikationer för en detaljerad lista.
+ Säker säkerhetskopiering
+ Sätt upp säker säkerhetskopiering
+ Återställ säker säkerhetskopiering
+ Sätt upp på den här enheten
+ Generera en ny säkerhetskopia eller sätt en ny lösenfras för din existerande säkerhetskopia.
+ Sessionsinformation
+ Detta är experimentella funktioner som kan gå sönder på oväntade sätt. Använd varsamt.
+ Kryptera endast till verifierade sessioner
+ Algoritm
+ Sessions-ID
+ Avsändarens sessionsinformation
+ Sessions-ID
+ Sessionsnyckel
+ Exportera krypteringsnycklar
+ Exportera rumsnycklar
+ Exportera
+ Vänligen skapa en lösenfras för att kryptera de exporterade nycklarna. Du kommer behöva skriva in samma lösenfras för att kunna importera nycklarna.
+ Hantera nyckelsäkerhetskopiering
+
+ Importera krypteringsnycklar
+ Importera rumsnycklar
+ Importera
+ Kryptera endast till verifierade sessioner
+ okänd session
+ Verifiera session
+ Rummet innehåller okända sessioner
+ Detta alternativ kräver en tredjepartsapplikation för att spela in meddelandena.
+ Du har lagt till en ny session \'%s\', vilken begär krypteringsnycklar.
+ En ny session begär krypteringsnycklar. Sessionsnamn: %1$s
+\nSenast sedd: %2$s
+\nOm du inte loggade in i en annan session, ignorera denna begäran.
+ Din overifierade session \'%s\' begär krypteringsnycklar.
+ En ny session begär krypteringsnycklar.
+\nSessionsnamn: %1$s
+\nSenast sedd: %2$s
+\nOm du inte loggade in i en annan session, ignorera denna begäran.
+
+ Markdown har aktiverats.
+ Markdown har inaktiverats.
+
+ För att fortsätta använda hemservern %1$s så måste du läsa och godkänna användarvillkoren.
+ Ingen Matrixsession tillgänglig
+
+ Börja använda nyckelsäkerhetskopiering
+ Exportera nycklar manuellt
+
+ Säkra din säkerhetskopia med en lösenfras.
+ Eller säkra din säkerhetskopia med en återställningsnyckel och spara den någonstans säkert.
+ Dina nycklar säkerhetskopieras.
+ Det ser ut som att du redan har konfigurerat säker säkerhetskopiering från en annan session. Vill du ersätta den med den du skapar\?
+ Dina krypteringsnycklar säkerhetskopieras just nu till din hemserver i bakgrunden. Den initiala säkerhetskopieringen kan ta flera minuter.
+
+
+ Förlorat din återställningsnyckel\? Du kan sätta upp en ny i inställningarna.
+ Säkerhetskopieringen kunde inte avkrypteras med den här återställningsnyckeln: vänligen verifiera att du skrev in rätt återställningsnyckel.
+
+
+ Återställde en säkerhetskopia med %d nyckel.
+ Återställde en säkerhetskopia med %d nycklar.
+
+
+ %d ny nyckel har lagts till till den här sessionen.
+ %d nya nycklar har lagts till till den här sessionen.
+
+
+ Sessionskrypto är inte aktiverats
+
+
+ Återställ från säkerhetskopia
+ Radera säkerhetskopia
+
+ Nyckelsäkerhetskopiering har blivit korrekt konfigurerad för den här sessionen.
+ Nyckelsäkerhetskopiering är inte aktiverad på den här sessionen.
+ Dina nycklar säkerhetskopieras inte från den här sessionen.
+
+ Säkerhetskopian har en signatur från en okänd session med ID %s.
+ Säkerhetskopian har en giltig signatur från den här sessionen.
+ Säkerhetskopian har en giltig signatur från den verifierade sessionen %s.
+ Säkerhetskopian har en giltig signatur från den overifierade sessionen %s
+ Säkerhetskopian har en ogiltig signatur från den verifierade sessionen %s
+ Säkerhetskopian har en ogiltig signatur från den overifierade sessionen %s
+ För att använda nyckelsäkerhetskopiering i den här sessionen, återställ med din lösenfras eller återställningsnyckel nu.
+ Misslyckades att radera säkerhetskopia (%s)
+
+ Radera säkerhetskopia
+ Ny nyckelsäkerhetskopia
+ Börja använda nyckelsäkerhetskopiering
+
+ Säker säkerhetskopiering
+ Använd nyckelsäkerhetskopiering
+
+ Hantera i nyckelsäkerhetskopieringen
+
+ Sätt upp säker säkerhetskopiering
+
+ Alla nycklar säkerhetskopierade
+ Algoritm
+ Att verifiera den här sessionen kommer att markera den som betrodd, och även markera din session som betrodd för den andra parten.
+
+ Verifiera den här sessionen genom att bekräfta att följande emojier visas på den andra partens skärm
+ Verifiera den här sessionen genom att bekräfta att följande nummer visas på den andra partens skärm
+
+ Du har framgångsrikt verifierat den här sessionen.
+ Den andra parten avbröt verifikationen.
+\n%s
+ Interaktiv sessionsverifiering
+ %s vill verifiera din session
+
+ Sessionen känner inte till den överföringen
+ Sessionen kan inte komma överens om ett nyckelavtal, hash, MAC eller SAS-metod
+ Visa borttagna meddelanden
+ Visa en platshållare för borttagna meddelanden
+ Annan information från tredje part
+ Pushregler
+ Inga pushregler satta
+ Visa dolda händelser i tidslinjen
+
+ Tillåt att svajpa för att svara i tidslinjen
+ Lägg till en dedikerad flik för olästa aviseringar på startskärmen.
+
+ Aktivera mångordiga loggar.
+ Vänligen försök igen när du har godkänt användarvillkoren för din hemserver.
+
+
+ %1$s, %2$s och %3$d annan har läst
+ %1$s, %2$s och %3$d andra har läst
+
+ Element behöver behörighet för att spara dina nycklar för totalsträckskryptering i lagringen.
+\n
+\nVänligen ge tillstånd i nästa popup för att kunna manuellt exportera dina nycklar.
+
+ Du ignorerar inga användare
+
+ Annan
+ Om du har skapat ett konto på en hemserver så kan du använda ditt Matrix-ID (t.ex. @användare:domän.com) och lösenord nedan.
+ Detta kan bero på flera orsaker:
+\n
+\n• Du har ändrat ditt lösenord från en annan session.
+\n
+\n• Du har tagit bort den här sessionen från en annan session.
+\n
+\n• Serveradministratören har tagit bort din åtkomst av säkerhetsskäl.
+ Varning: Din personliga data (inklusive krypteringsnycklar) lagras fortfarande på den här enheten.
+\n
+\nRensa den om du inte ska använda den här enheten längre, eller vill logga in på ett annat konto.
+ Den nuvarande sessionen är för användaren %1$s och du försedde uppgifter för användaren %2$s. Detta stöds inte av Element.
+\nVänligen rensa först data, och logga sen in på ett annat konto.
+
+ Se alla mina sessioner
+ Utvecklarläge
+ Utvecklarläget aktiverar dolda funktioner och kan också göra appen mindre stabil. Endast för utvecklare!
+ Raseriskakning
+ Detektionsgräns
+ Skaka din mobil för att testa detektionsgränsen
+ Nuvarande session
+ Andra sessioner
+
+ Misslyckas snabbt
+ En av följande kan vara äventyrad:
+\n
+\n - Din hemserver
+\n - Hemservern användaren du verifierar är ansluten till
+\n - Din eller den andra användarens internetanslutning
+\n - Din eller den andra användarens enhet
+
+ Verifiera den här sessionen
+ Skanna koden med den andra användarens enhet för att säkert verifiera varandra
+ Tidslinje
+
+ Jämför koden med den som visas på den andra användarens skärm.
+ Korssignering
+ Korssignering är aktiverad
+\nPrivata nycklar finns på enheten.
+ Korssignering är aktiverad
+\nNycklar är betrodda.
+\nPrivata nycklar är inte kända
+ Korssignering är aktiverad
+\nNycklar är inte betrodda
+ Korssignering är inte aktiverat
+
+ Aktiva sessioner
+ Visa alla sessioner
+ Hantera sessioner
+ Logga ut ur den här sessionen
+
+ Den här sessionen är betrodd för säker kommunikation för att du verifierade den:
+
+ %d aktiv session
+ %d aktiva sessioner
+
+
+ Andra användare kanske inte litar på den
+ Misslyckades att hämta sessioner
+ Sessioner
+ Den här sessionen är betrodd för säker kommunikationen för säker kommunikation för att %1$s (%2$s) verifierade den:
+ %1$s (%2$s) loggade in i en ny session:
+ Tills den här användaren litar på den här sessionen så kommer meddelanden skickade till och från den att bli märkta med varningar. Alternativt så kan du manuellt verifiera den.
+
+
+ Utvecklarverktyg
+ Kontodata
+ Om du inte kan komma åt en existerande session
+
+ Nyckelförfrågningar
+
+ En av följande kan vara äventyrad:
+\n
+\n- Ditt lösenord
+\n- Din hemserver
+\n- Den här enheten, eller den andra enheten
+\n- Internetuppkopplingen en av enheterna använder
+\n
+\nVi rekommenderar att du ändrar ditt lösenord och återställningsnyckel i inställningarna omedelbart.
+
+ Sätter upp nyckelsäkerhetskopiering
+
+
+ Spara den på ett USB-minne eller en säkerhetskopieringsenhet
+ Nästan färdigt! Visar den andra enheten samma sköld\?
+ Misslyckades att importera nycklar
+
+ Aktivera korssignering
+ Kollar säkerhetskopieringsnyckel
+ Kollar säkerhetskopieringsnyckel (%s)
+ Skriv in din lösenfras för säkerhetskopiering för att fortsätta.
+ använda din återställningsnyckel för säkerhetskopiering
+ Om du inte känner till din lösenfras för säkerhetskopia så kan du %s.
+ Återställningsnyckel för säkerhetskopiering
+
+ Förhindra skärmdumpar av appen
+ Att aktivera den här inställningen lägger till FLAG_SECURE till alla aktiviteter. Starta om appen för att inställningen ska få effekt.
+
+ Använd senaste Element på dina andra enheter; Element Web, Element iOS, Element för Android, eller annan Matrixklient som stöder korssignering
+ eller en annan Matrixklient som städer korssignering
+ Använd senaste Element på dina andra enheter:
+ Tvingar den nuvarande utgående gruppsessionen i ett krypterat rum att kasseras
+ Säkerhetskopian kunde inte avkrypteras med den här återställningsnyckeln: vänligen verifiera att du skrev in rätt återställningsnyckel.
+ Sätt upp säker säkerhetskopiering
+
+ Säker säkerhetskopiering
+ Sätt upp
+ Skriv in en hemlig fras endast du känner till, och generera en nyckel för säkerhetskopiering.
+
+ Element kommer att synka i bakgrunden på ett sätt som sparar på enhetens begränsade resurser (batteri).
+\nBeroende på din enhets resurser, så kan synkroniseringen bli uppskjuten av operativsystemet.
+ Optimerad för realtid
+ Ingen bakgrundssynk
+ Du kommer inte att bli aviserad om inkommande meddelanden när appen är i bakgrunden.
+ Misslyckades att uppdatera inställningarna.
+
+
+ Starta vid boot
+ Aktivera bakgrundssynk
+ Timeout för synkbegäran
+ Föredraget synkintervall
+ %s
+\nSynkroniseringen kan skjutas upp beroende på resurserna (batteri) eller status för enheten (vila).
+ Fördröjning mellan varje synkronisering
+ sekund
+ sekunder
+
+ Lokala kontakter
+ Kontaktbehörighet
+ Land för telefonbok
+ Hemskärm
+ Inbäddade URL-förhandsgranskningar
+ Förhandsgranska länkar i chatten om din hemserver stöder den här funktionen.
+ Visa tidsstämplar i 12-timmarsformat
+ Inbjudningar, utsparkningar och bann påverkas inte.
+ Visa kontohändelser
+ Vibrera när en användare nämns
+ Hantera
+ Detta kommer att ersätta din nuvarande nyckel eller fras.
+
+ Ge behörighet
+ Välj ett annat alternativ
+
+ Bakgrundsanslutning
+ Ge behörighet
+
+ Statistik
+ Skicka statistikdata
+ Element samlar in anonym statistik för att låta oss förbättra appen.
+ Vänligen aktivera statistik för att hjälpa oss att förbättra Element.
+ Ja, jag vill hjälpa till!
+
+ Databesparingsläge
+ ID
+ Publikt namna
+ Uppdatera publikt namn
+ Senast sedd
+ %1$s @ %2$s
+ Autentisering
+ Skicka in
+
+ Integrationshanterare
+
+ Verifikation pågår
+ Det här telefonnumret används redan.
+ Lösenorden matchar inte
+
+ Är du säker på att du vill ta bort %1$s %2$s\?
+
+ Välj ett land
+
+ Land
+ Vänligen välj ett land
+ Telefonnummer
+ Ogiltigt telefonnummer för det valda landet
+ Telefonverifiering
+ Vi har skickat ett SMS med en aktiveringskod. Vänligen skriv denna kod nedan.
+ Skriv en aktiveringskod
+ Fel vid validering av ditt telefonnummer
+ Kod
+ Ett fel inträffade vid verifiering av ditt telefonnummer.
+ Ytterligare info: %s
+
+ Förvald komprimering
+ Välj
+ Välj
+ Spela slutarljud
+
+ 3 dagar
+ 1 vecka
+ 1 månad
+ För alltid
+
+ Rumsbild
+ Rumsnamn
+ Ämne
+ Rumsetikett
+ Märkt som:
+
+ Favorit
+ Låg prioritet
+ Ingen
+
+ Behörighet och synlighet
+ Lista det här rummet i rumskatalogen
+ Rumstillgång
+ Synlighet för rumshistorik
+ Vem kan läsa historiken\?
+ Vem kan komma åt det här rummet\?
+
+ Vem som helst
+ Endast medlemmar (från när det här alternativet valdes)
+ Endast medlemmar (sen de bjöds in)
+ Endast medlemmar (sen de gick med)
+
+ För att länka till ett rum så måste det ha en adress.
+ Vem som helst som har rummets adress, förutom gäster
+ Vem som helst som har rummets adress, inklusive gäster
+
+ Bannade användare
+
+ %d bannad användare
+ %d bannade användare
+
+
+ Rummets interna ID
+ Adresser
+ Du behöver logga ut för att kunna aktivera krypteringen.
+ Det här rummet har inga lokala adresser
+ Ny adress (t.ex. #foo:matrix.org)
+
+ Nytt gemenskaps-ID (t.ex. +foo:matrix.org)
+ Ogiltigt gemenskaps-ID
+ \'%s\' är inte ett giltigt gemenskaps-ID
+
+
+ Ogiltigt aliasformat
+ \'%s\' är inte ett giltigt format för ett alias
+ Du kommer inte att ha någon huvudadress specificerad för det här rummet.
+ Huvudadressvarningar
+
+ Sätt som huvudadress
+ Avsätt som huvudadress
+ Kopiera rums-ID
+ Kopiera rumsadress
+
+ Kryptering är avaktiverat i det här rummet.
+ Aktivera kryptering
+\n(varning: kan inte avaktiveras igen!)
+
+ Katalog
+ Händelseinformation
+ Användar-ID
+ Curve25519-identitetsnyckel
+ Gjorde anspråk på Ed25519-fingeravtrycksynyckel
+ Avkrypteringsfel
+
+ Publikt namn
+ Publikt namn
+ Verifiering
+ Ed25519-fingeravtryck
+
+ Nycklar framgångsrikt importerade
+
+
+ %1$d/%2$d nyckel importerad framgångsrikt.
+ %1$d/%2$d nycklar importerade framgångsrikt.
+
+
+ Inte verifierad
+ Verifierad
+ Svartlistad
+
+ okänd IP
+ ingen
+
+ Verifiera
+ Avverifiera
+ Svartlista
+ Avsvartlista
+
+ Om de inte matchar så kan kommunikationens säkerhet vara äventyrad.
+ Jag verifierar att nycklarna matchar
+
+ Servern kan vara otillgänglig eller överbelastad
+ Hemserver-URL
+ Skriv här…
+
+ %1$s i %2$s
+ Ny händelse
+ Rum
+ Nya meddelanden
+ Nya inbjudningar
+ Jag
+ ** Misslyckades att skicka - vänligen öppna rummet
+ %1$s: %2$s
+ %1$s: %2$s %3$s
+
+ Sök efter historiska
+
+ Du behöver behörighet för att hantera widgets i det här rummet
+ Widgetskapande har misslyckats
+ Skapa gruppsamtal med Jitsi
+ Är du säker på att du vill radera den här widgeten från det här rummet\?
+
+ 1 aktiv widget
+ %d aktiva widgets
+
+ VISA
+ Aktiva widgets
+
+
+ Widgets
+ Ladda widget
+ Den här widgeten lades till av:
+ Att använda den kan sätta kakor och dela data med %s:
+ Att använda den kan dela data med %s:
+ Misslyckades att ladda widgeten.
+\n%s
+ Ladda om widget
+ Öppna i webbläsaren
+ Återkalla tillgång för mig
+
+ Din avatar-URL
+ Ditt användar-ID
+ Widget-ID
+ Rums-ID
+
+
+ Tyvärr, gruppsamtal med Jitsi stöds inte på gamla enheter (enheter med Android äldre än 5.0)
+ Den här widgeten vill använda följande resurser:
+ Tillåt
+ Blockera alla
+ Använd mikrofonen
+ Kunde inte skapa widgeten.
+ Misslyckades att skicka begäran.
+ Behörighetsnivå måste vara ett positivt heltal.
+ Du är inte i det här rummet.
+ Du har inte behörighet att göra det i det här rummet.
+ Saknar room_id i begäran.
+ Saknar user_id i begäran.
+ Rummet %s är inte synligt.
+ En krävd parameter saknas.
+ En parameter är inte giltig.
+ Ingen integrationshanterare konfigurerad.
+ Hantera integrationer
+ Inga aktiva widgets
+ Skicka röstmeddelanden
+ För att fortsätta behöver du acceptera villkoren för den här tjänsten.
+
+ Starta verifiering
+ Verifiera
+ Dela utan att verifiera
+ Dela
+ Nyckeldelningsbegäran
+ Ignorera begäran
+ Ignorera
+
+ Varning!
+ Gruppsamtal är under utveckling och kanske inte är pålitligt.
+
+ Kommandofel
+ Okänt kommando: %s
+ Visar handling
+ Bannar användaren med det angivna ID:t
+ Avbannar användaren med det angivna ID:t
+ Definiera behörighetsnivå för en användare
+ Avoppar användaren med det angivna ID:t
+ Bjuder in användaren med det angivna ID:t till det nuvarande rummet
+ Går med i rummet med det angivna aliaset
+ Sätt ett rumsämne
+ Sparkar ut användaren med det angivna ID:t
+ Ändrar ditt visningsnamn
+ För att fixa Matrixapphantering
+
+ Skapa
+ Skapa gemenskap
+ Gemenskapsnamn
+ Exempel
+ Gemenskaps-ID
+ exempel
+
+ Hem
+ Inga användare
+
+ Gick med
+ Bjöd in
+
+ 1 medlem
+ %d medlemmar
+
+
+ Gemenskapsadministratören har inte försett en lång beskrivning för den här gemenskapen.
+
+ Du har blivit utsparkad från %1$s av %2$s
+ Du har blivit bannad från %1$s av %2$s
+ Orsak: %1$s
+ Gå med igen
+ Glöm rummet
+
+ Läsindikationsavatar
+ Notisavatar
+ Avatar
+
+ Granska nu
+
+ Vänligen skriv in ett användarnamn.
+ Det här rummet har blivit ersatt och är inte längre tillgängligt
+ Samtalet fortsätter här
+ Det här rummet är en fortsättning av en annan konversation
+ Tryck här för att se äldre meddelanden
+
+ Resursgränsen överskriden
+ Hemservern har överskridit en av sina resursbegränsningar så vissa användare kommer inte att kunna logga in.
+ Den här hemservern har överskridit en av sina resursbegränsningar.
+
+ Den här hemservern har nått sin månatliga aktiva användargräns så vissa användare kommer inte att kunna logga in.
+ Den här hemservern har nått sin månatliga aktiva användargräns.
+
+ Vänligen %s för att öka den här gränsen.
+ Vänligen %s för att fortsätta använda den här tjänsten.
+
+ Din hemserver stöder inte fördröjd inladdning av rumsmedlemmar än. Försök igen senare.
+
+ Tyvärr, ett fel inträffade
+
+ expandera
+ kollapsa
+
+ Visa infoarean
+ Alltid
+ För meddelanden och fel
+ Endast för fel
+
+ %1$s:
+ %1$s: %2$s
+ +%d
+ %d+
+ Skapa lösenfras
+ Bekräfta lösenfras
+ Skriv lösenfras
+ Lösenfrasen matchar inte
+ Vänligen skriv en lösenfras
+ Lösenfrasen är för svag
+
+ Vänligen radera lösenfrasen om du vill att Element ska generera en återställningsnyckel.
+ Sätt lösenfras
+ Skapar säkerhetskopia
+ Framgång !
+ Klar
+ Jag har gjort en kopia
+ Spara återställningnyckel
+ Dela
+ Återställningsnyckeln har sparats.
+
+ En säkerhetskopia finns redan på din hemserver
+ Ersätt
+ Stoppa
+
+ Vänligen gör en kopia
+ Dela återställningsnyckel med…
+ Genererar återställningsnyckel med hjälp av lösenfras, den här processen kan ta flera sekunder.
+ Återställningsnyckel
+ Oväntat fel
+ Säkerhetskopiering startad
+ Är du säker\?
+ Du kan förlora åtkomst till dina meddelanden om du loggar ut ur eller förlorar den här enheten.
+
+ använd din återställningsnyckel
+ Kan du inte din återställningslösenfras så kan du %s.
+
+ Skriv in återställningsnyckel
+
+ Säkerhetskopian kunde inte avkrypteras med den här lösenfrasen: vänligen verifiera att du skrev in rätt lösenfras.
+ Nätverksfel: vänligen kolla din anslutning och försök igen.
+
+ Återställer säkerhetskopia:
+ Räknar ut återställningsnyckel…
+ Laddar ner nycklar…
+ Importerar nycklar…
+ Låser upp historia
+ Vänligen skriv in en återställningsnyckel
+ Säkerhetskopia återställd %s !
+ Misslyckades att få betroendeinfo för säkerhetskopian (%s).
+
+ Raderar säkerhetskopia…
+ Kollar status för säkerhetskopian
+ Det var jag
+
+ Säkerhetskopierar dina nycklar. Detta kan ta flera minuter…
+
+
+
+ Säkerhetskopierar %d nyckel…
+ Säkerhetskopierar %d nycklar…
+
+
+ Signatur
+
+ Autokomplettera serveralternativ
+ Element detekterade en anpassad serverkonfiguration för din användar-ID-domän \"%1$s\":
+\n%2$s
+ Använd konfig
+
+ Verifiera genom att jämföra en kort textsträng.
+ För maximal säkerhet så rekommenderar vi att du gör det här personligen eller med en annan pålitlig form av kommunikation.
+ Påbörja verifiering
+ Inkommande verifieringsbegäran
+ Du mottog en inkommande verifieringsbegäran.
+ Visa begäran
+ Väntar på att den andra parten ska bekräfta…
+
+ Verifierad!
+ Jag förstår
+
+ Dyker inget upp\? Inte alla klienter stöder interaktiv verifiering än. Använd legacyverifiering.
+ Använd legacyverifiering.
+
+ Nyckelverifiering
+ Begäran avbruten
+ Verifieringen är avbruten.
+\nAnledning: %s
+
+ Verifieringsbegäran
+ Användaren avbröt verifieringen
+ Verifieringsprocessen timeade ut
+ Hashåtagandet matchade inte
+ SAS:en matchade inte
+ Nyckelmismatch
+ Användarmismatch
+ Okänt fel
+
+ Det verkar som att du försöker ansluta till en annan hemserver. Vill du logga ut\?
+
+ Redigera
+ Svara
+
+ Försök igen
+ Gå med i ett rum för att börja använda appen.
+ Skickade en inbjudan till dig
+ Inbjuden av %s
+
+ Välkommen hit!
+ Kom ikapp med olästa meddelanden här
+ Konversationer
+ Reaktioner
+ Acceptera
+ Gilla
+ Lägg till reaktion
+ Visa reaktioner
+ Reaktioner
+
+ Händelsen raderades av användaren
+ Händelsen modererades av en rumsadministratör
+ Senast redigerad av %1$s vid %2$s
+
+
+ Felformaterad händelse, kan inte visa
+ Inget nätverk. Vänligen kolla din internetanslutning.
+ Ändra
+ Vänligen vänta…
+ Det här rummet kan inte förhandsgranskas
+ Förhandsgranskning av världsläsbara rum stöds inte än av Element
+
+ Nytt rum
+ SKAPA
+ Rumsnamn
+ Publikt
+ Vem som helst kommer kunna gå med i det här rummet
+ Rumskatalog
+ Publicera det här rummet till rumskatalogen
+ Rummet har skapats, men vissa inbjudningar har inte skickats av följande anledning:
+\n
+\n%s
+
+ Ett fel inträffade vi hämtning av betroendeinfo
+ Ett fel inträffade vid hämtning av nyckelsäkerhetskopia
+
+ Du tittar redan på det här rummet!
+
+ Snabbreaktioner
+
+ Expert
+ Inga registrerade pushgateways
+
+ app_id:
+ push_key:
+ app_display_name:
+ session_name:
+ Url:
+ Format:
+
+ Registrera token
+
+ Väntar…
+ Krypterar miniatyrbild…
+ Skickar miniatyrbild (%1$s / %2$s)
+ (redigerad)
+
+ Inga redigeringar funna
+
+ Länk kopierad till klippbordet
+
+ Skapar rum…
+ Börja skriva för att få resultat
+ Går med i rummet…
+
+ Visa redigeringshistoria
+
+ Användarvillkor
+ Granska villkor
+ Läst vid
+
+
+ Väntar
+
+ Verifikationskoden är felaktig.
+
+ Det verkar som att servern tar för lång tid att svara. Detta kan orsakas av antingen dålig uppkoppling eller ett fel på servern. Vänligen försök igen senare.
+
+ Skicka bilaga
+
+ Öppna navigationslådan
+ Öppna rumskapandemenyn
+ Stäng rumskapandemenyn…
+ Stäng nyckelsäkerhetskopieringsbannern
+ Hoppa till botten
+
+ %1$s, %2$s och %3$s läste
+ %1$s och %2$s läste
+ %s läste
+
+ 1 användare läste
+ %d användare läste
+
+
+ Ett fel inträffade vid hämtning av bilagan.
+ Kunde inte hantera delningsdata
+
+ %1$s vid %2$s
+ Det är skräppost
+ Det är olämpligt
+ Anpassad rapport…
+ Rapportera det här innehållet
+ Anledning till att rapportera detta innehåll
+ RAPPORTERA
+ IGNORERA ANVÄNDARE
+
+ Innehåll rapporterat
+ Rapporterad som skräppost
+ Rapporterad som olämplig
+ Det finns ingen nätverksanslutning just nu
+
+ Ignorera användare
+
+ Inställningar
+ Lägg till i favoriter
+ Ta bort från favoriter
+ %1$s gjorde inga ändringar
+ Du gjorde inga ändringar
+ Spoiler
+ %1$s gjorde rummet publikt för alla som har länken.
+ Du gjorde rummet publikt för alla som har länken.
+ Du ändrade rummet till endast inbjudna.
+ Olästa meddelanden
+
+ Det är din konversation. Äg det.
+ Håll konversationer privata med kryptering
+ Utöka och anpassa din upplevelse
+ Kom igång
+
+ Välj en server
+ Premiumservervärd för organisationer
+ Fortsätt
+ Anslut till %1$s
+ Anslut till Element Matrix Services
+ Anslut till en annan server
+ Logga in på %1$s
+ Bli medlem
+ Logga in
+ Fortsätt med SSO
+
+ Element Matrix Services-adress
+ Adress
+ Premiumservervärd för organisationer
+ Skriv in adressen för Modular Element eller servern du vill använda
+ Skriv in adressen för en server eller Element du vill ansluta till
+ Skriv in adressen för servern du vill använda
+
+ Ett fel inträffade vid laddning av sidan: %1$s (%2$d)
+ Appen kan inte logga in på den här hemservern. Hemservern stöder följande inloggninstyp(er): %1$s.
+\n
+\nVill du logga in med en webbklient\?
+ Tyvärr, den här servern accepterar inte nya konton.
+ Appen kan inte skapa ett konto på den här hemservern.
+\n
+\nVill du registrera dig med en webbklient\?
+
+ Nästa
+ Varning!
+ Fortsätt
+
+ Kolla din inkorg
+ Tryck på länken för att bekräfta ditt nya lösenord. När du har följt länken det innehåller, klicka nedan.
+ Framgång!
+ Ditt lösenord har återställts.
+ Tillbaka till inloggning
+
+ Varning
+ Ditt lösenord har inte ändrats än.
+\n
+\nVill du avbryta återställningsprocessen\?
+
+ Nästa
+
+ Sätt telefonnummer
+ Vänligen använd internationellt format.
+ Telefonnummer
+ Telefonnummer (valfritt)
+ Nästa
+
+ Bekräfta telefonnummer
+ Vi skickade just en kod till %1$s. Skriv in den nedan för att bekräfta att det är du.
+ Skriv in kod
+ Skicka igen
+ Nästa
+
+ Internationella telefonnummer måste börja med \'+\'
+ Telefonnumret verkar vara ogiltigt. Vänligen kolla det
+
+ Logga in på %1$s
+ Användarnamn
+ Lösenord
+ Nästa
+ Det användarnamnet är upptaget
+ Varning
+ Ditt konto är inte skapat än.
+\n
+\nVill du avbryta registreringsprocessen\?
+
+ Välj matrix.org
+ Välj Element Matrix Services
+ Välj en annan hemserver
+ Vänligen utför captchautmaningen
+ Acceptera villkoren för att fortsätta
+
+ Den inskrivna koden är felaktig. Vänligen kolla den.
+ Utdaterad hemserver
+
+ För många förfrågningar har skickats. Du kan försöka igen om %1$d sekund…
+ För många förfrågningar har skickats. Du kan försöka igen om %1$d sekunder…
+
+
+ Alternativt, om du redan har ett konto och du kan ditt Matrix-ID och ditt lösenord, så kan du använda den här metoden:
+ Logga in med ditt Matrix-ID
+ Logga in med ditt Matrix-ID
+ Matrix-ID
+ Om du inte kan ditt lösenord, gå tillbaka för att återställa det.
+ Det här är inte ett giltigt användar-ID. Förväntat format: \'@användare:hemserver.org\'
+ Sett av
+
+ Du är utloggad
+ Logga in igen
+
+ Du är utloggad
+ Logga in
+ Administratören för din hemserver (%1$s) har loggat ut dig ur ditt konto %2$s (%3$s).
+ Logga in
+ Lösenord
+ Rensa personlig information
+ Rensa all data
+
+ Rensa data
+ Du kommer att bli av med åtkomsten till dina krypterade meddelanden om du inte loggar in igen för att återfå dina krypteringsnycklar.
+ Rensa data
+ Din matrix.to-länk var felformaterad
+ Beskrivningen är för kort
+
+ Inledande synk…
+
+ Skakning upptäckt!
+ Inställningar
+ Aktivera kryptering
+ Obetrodd inloggning
+ De matchar
+ De matchar inte
+ Verifiera den här användaren genom att bekräfta att följande unika emojier visas på hens skärm i samma ordning.
+ För maximal säkerhet, använd en annan pålitlig kommunikationsform eller gör detta personligen.
+ Kolla efter den gröna skölden för att försäkra dig om att en användare är betrodd. Lita på alla användare i ett rum för att försäkra dig om att rummet är säkert.
+
+ Inte säker
+ Video.
+ Bild.
+ Väntar…
+ %s avbröt
+ Du avbröt
+ %s accepterade
+ Du accepterade
+ Verifikation skickad
+ Verifieringsbegäran
+ Verifiera manuellt
+
+ Du
+
+ Skanna deras kod
+ Kan inte skanna
+ Om ni inte träffas personligen, jämför emojier istället
+
+ Verifiera genom att jämföra emojier
+
+ Verifiera med emojier
+ Om du inte kan skanna koden ovan, verifiera genom att jämföra ett kort, unikt urval av emojier.
+
+ QR-kodsbild
+
+ Verifiera %s
+ Verifierade %s
+ Väntar på %s…
+ För extra säkerhet, verifiera %s genom att kolla en engångskod på båda era enheter.
+\n
+\nFör maximal säkerhet, gör detta personligen.
+ Säkerhet
+ Adminhandlingar
+ Lämnar rummet…
+
+ Anpassad
+ Inbjudningar
+ Användare
+
+ Administratör i %1$s
+ Moderator i %1$s
+ Standard i %1$s
+ Anpassad (%1$d) i %2$s
+
+ Hoppa till läsindikation
+
+ Element hanterar inte händelser av typen \'%1$s\'
+ Element stötte på ett fel vid rendering av innehållet i händelsen med id \'%1$s\'
+
+ Avignorera
+
+ Skickar den givna emoten i regnbågsfärg
+
+ Godkänn
+ Avslå
+ Lägg på
+
+ Aktivera kryptering\?
+ Aktivera kryptering
+
+ För att vara säker, verifiera %s genom att kolla en engångskod.
+ För att vara säker, gör detta personligen eller använd en annan säker kommunikationsform.
+
+ Jämför de unika emojierna, och försäkra dig om att de visas i samma ordning.
+ Din serveradministratör har inaktiverat totalsträckskryptering som förval för privata rum och direktmeddelanden.
+ Ingen kryptografisk information tillgänglig
+
+ Verifiera den här inloggningen
+ Fullborda säkerhet
+
+ Verifiera
+ Verifierad
+ Varning
+
+ Betrodd
+ Inte betrodd
+
+ Initierar korssignering
+ Återställ nycklar
+
+ QR-kod
+
+ Nästan färdigt! Ser %s samma sköld\?
+ Ja
+ Nej
+
+ Anslutningen till servern har tappats
+ Flygplansläge är på
+
+
+ %d röst
+ %d röster
+
+
+ %d röst - Slutgiltigt resultat
+ %d röster - Slutgiltigt resultat
+
+ Valt alternativ
+ Skapar en enkel omröstning
+ Använd en återställningslösenfras eller -nyckel
+ Ny inloggning
+
+ Skriv in en lösenfras för hemlig lagring
+ Varning:
+ Du bör endast komma åt hemlig lagring från en betrodd enhet
+
+ Ta bort…
+ Vill du skicka den här bilagan till %1$s\?
+
+ Skicka bild i originalstorlek
+ Skicka bilder i originalstorlek
+
+
+ Bekräfta borttagning
+ Är du säker på att du vill ta bort (radera) den här händelsen\? Observera att om du raderar ett rumsnamn eller ämnesändring så kan det upphäva ändringen.
+ Inkludera en anledning
+ Anledning för borttagning
+
+ Händelsen raderades av användaren, anledning: %1$s
+ Händelsen modererades av rumsadministratören. Anledning: %1$s
+
+ Nycklarna är redan uppdaterade!
+
+ Element Android
+
+ Ladda om
+
+ Ny inloggning. Var det du\?
+ Tryck för att granska och verifiera
+ Det var inte jag
+ Ditt konto kan vara äventyrat
+
+ Verifiera dina enheter i inställningarna.
+ Verifikation avbruten
+
+ återställningslösenfras
+ kontolösenord
+
+ Sätt en %s
+ Bekräfta %s
+
+ Skriv in ditt %s för att fortsätta.
+
+ Skriv in din %s igen för att fortsätta.
+ Använd inte ditt kontolösenord.
+
+ Skriv in en säkerhetsfras endast du känner till, vilken används för att säkra hemligheter på din server.
+
+ Detta kan ta flera sekunder, ha tålamod.
+ Sätter upp återställning.
+ Din återställningsnyckel
+ Du är färdig!
+ Håll den säker
+ Slutför
+
+ Använd denna %1$s som ett skyddsnät ifall du glömmer din %2$s.
+
+ Publicerar skapade identitetsnycklar
+ Genererar säkra nycklar baserat på lösenfras
+ Definierar förvald nyckel för SSSS
+ Synkroniserar huvudnyckel
+ Synkroniserar användarnyckel
+ Synkroniseras självsigneringsnyckel
+ Skriv ut den och spara den någonstans säkert
+ Kopiera den till din personliga molnlagring
+
+ Du kan inte göra det där på mobilen
+
+ Krypteringen som används i det här rummet stöds inte
+
+ %s skapade och konfigurerade rummet.
+ Du skapade och konfigurerade rummet.
+
+ Nästan färdigt! Väntar på bekräftelse…
+ Väntar på %s…
+
+ Felaktigt användarnamn och/eller lösenord. Lösenordet du skrev börjar eller slutar med mellanslag, vänligen kolla det.
+ Kontot har inaktiverats.
+
+ Krypteringsuppgradering tillgänglig
+ Verifiera dig själv och andra för att hålla dina chattar säkra
+
+ Skriv in din %s för att fortsätta
+ Skriv in %s
+ Återställningslösenfras
+ Det är inte en giltig återställningsnyckel
+ Vänligen skriv in en återställningsnyckel
+
+ Hämtar kurvnyckel
+ Generar SSSS-nyckel baserat på lösenfras
+ Generar SSSS-nyckel baserat på lösenfras (%s)
+ Generar SSSS-nyckel baserat på återställningsnyckel
+ Lagrar hemlighet för nyckelsäkerhetskopiering i SSSS
+ %1$s (%2$s)
+
+ Element Webb
+\nElement Skrivbord
+ Element iOS
+\nElement Android
+ Använd din %1$s eller %2$s för att fortsätta.
+ Använd återställningsnyckel
+ Välj din återställningsnyckel eller mata in den manuellt genom att skriva den eller klistra in från klippbordet
+ Misslyckades att komma åt säker lagring
+
+ Okrypterad
+ Krypterad av en overifierad enhet
+ Verifiera den nya inloggningen på ditt konto: %1$s
+
+ Verifiera manuellt med text
+ Verifiera inloggning
+ Verifiera interaktivt med emojier
+ Markera som betrodd
+
+ Vänligen välj ett användarnamn.
+ Vänligen välj att lösenord.
+ Dubbelkolla den här länken
+ Länken %1$s tar dig till en annan sida: %2$s.
+\n
+\nÄr du säker på att du vill fortsätta\?
+
+ Lägg till medlemmar
+ Bjuder in användare…
+ Inbjudan skickad till %1$s
+ Inbjudan skickad till %1$s och %2$s
+ Öppna villkor för %s
+ Den här operationen är inte möjlig. Hemservern är utdaterad.
+ För ditt privatlivs skull stöder Element bara att skicka hashade e-postadresser och telefonnummer.
+ Associationen har misslyckats.
+ Det finns ingen nuvarande association med den här identifieraren.
+
+ Använd %1$s
+ Skicka in
+ Sätt roll
+ Roll
+ Öppna chatt
+ Tysta mikrofonen
+ Sluta tysta mikrofonen
+ Använd säkerhetsnyckel
+ Generera en säkerhetsnyckel att lagra någonstans säkert, som en lösenordshanterare eller ett kassaskåp.
+ Använd en säkerhetsfras
+ Spara din säkerhetsnyckel
+ Spara din säkerhetsnyckel någonstans säkert, som en lösenordshanterare eller ett kassaskåp.
+
+ Sätt an säkerhetsfras
+ Skriv in en säkerhetsfras endast du känner till, vilken används för att säkra hemligheter på din server.
+ Säkerhetsfras
+ Skriv in säkerhetsfrasen igen för att bekräfta den.
+
+ Spara din säkerhetsnyckel
+ Spara din säkerhetsnyckel någonstans säkert, som en lösenordshanterare eller ett kassaskåp.
+
+ Rumsnamn
+ Ämne
+ Du ändrade rumsinställningarna framgångsrikt
+
+ Kan inte avkryptera
+ Väntar på krypteringshistorik
+
+ Riot är nu Element!
+ Vi är glada att meddela att vi har bytt namn! Din app är uppdaterad och du är inloggad på ditt konto.
+ UPPFATTAT
+ LÄR DIG MER
+
+ element
+
+
+ Spara återställningsnyckel i
+
+ Lägg till från min telefonbok
+ Din telefonbok är tom
+ Telefonbok
+ Hämtar dina kontakter…
+ Kontaktbok
+
+ Återkalla inbjudan
+ Återkalla inbjudan av %1$s\?
+
+ Bannad av %1$s
+ Misslyckades att avbanna användaren
+
+ Pushnotiser är inaktiverade
+ Granska dina inställningar för att aktivera pushnotiser
+
+ Fel kod, %d försök kvar
+ Fel kod, %d försök kvar
+
+ Varning! Sista försöket innan du loggas ut!
+ För många fel, du har blivit utloggad
+ Välj en PIN-kod för säkerhet
+ Bekräfta PIN
+ Misslyckades med att validera PIN, vänligen skriv en ny.
+ Skriv din PIN-kod
+ Glömt PIN\?
+ Återställ PIN
+ Ny PIN
+ För att återställa din PIN-kod behöver du logga in igen och skapa en ny.
+ Aktivera PIN
+ Om du vill återställa din PIN-kod, tryck på \"Glömt PIN\?\" för att logga ut och återställa.
+ Bekräfta PIN för att återställa PIN
diff --git a/vector/src/main/res/values-th/strings.xml b/vector/src/main/res/values-th/strings.xml
index f19c51ff83..3ca04aae89 100644
--- a/vector/src/main/res/values-th/strings.xml
+++ b/vector/src/main/res/values-th/strings.xml
@@ -20,4 +20,90 @@
รหัสผ่านรหัสผ่านใหม่ลิงก์ถาวร
+ ข้อความ
+ ห้อง
+ การตั้งค่า
+ ข้อมูลสมาชิก
+ ตกลง
+ ยกเลิก
+ บันทึก
+ ออก
+ ส่ง
+ คัดลอก
+ ดาวน์โหลด
+ แชร์
+ พูด
+ ลบ
+ เปลี่ยนชื่อ
+ ข้าม
+ Thai
+
+ ส่งสติกเกอร์
+ กำลังโหลด…
+
+ ส่งต่อ
+ ไม่มี
+ รายงานเนื้อหา
+ เล่น
+ หยุดชั่วคราว
+ เสียง
+ วิดีโอ
+ หน้าหลัก
+ การแจ้งเตือน
+ ผู้คน
+ ห้อง
+ ชุมชน
+
+ การเชิญ
+ การแจ้งเตือนจากระบบ
+
+ คุณไม่ได้อนุญาตให้ Element เข้าถึงรายชื่อผู้ติดต่อในเครื่อง
+ ไม่มีผลลัพธ์
+ ไม่มีห้อง
+
+ ผู้ใช้ %d คน
+
+
+ เชิญ
+ ชุมชน
+ ไม่มีกลุ่ม
+
+ ถ้าเป็นไปได้ โปรดเขียนคำอธิบายเป็นภาษาอังกฤษ
+ อธิบายปัญหาของคุณที่นี่
+ ส่งไปยัง
+ เข้าห้อง
+ ชื่อผู้ใช้
+ สร้างบัญชี
+ เข้าสู่ระบบ
+ ออกจากระบบ
+ ค้นหา
+
+ เริ่มแชทใหม่
+ ลองโดยใช้ %s
+ ไม่ต้องถามฉันอีก
+
+ เลือกอุปกรณ์เสียง
+ โทรศัพท์
+ ลำโพง
+ หูฟัง
+ หูฟังไร้สาย
+ สลับกล้อง
+ หน้า
+ หลัง
+ ปิด HD
+ เปิด HD
+
+ ส่งสติกเกอร์
+ เข้าสู่ระบบ
+ สร้างบัญชี
+ ส่ง
+ ส่งอีเมลรีเซ็ต
+ กลับไปที่หน้าเข้าสู่ระบบ
+ อีเมลหรือชื่อผู้ใช้
+ ชื่อผู้ใช้
+ ที่อยู่อีเมล
+ ที่อยู่อีเมล (ไม่จำเป็น)
+ หมายเลขโทรศัพท์
+ หมายเลขโทรศัพท์ (ไม่จำเป็น)
+ รหัสผ่านสั้นเกินไป (อย่างน้อย 6 ตัว)
diff --git a/vector/src/main/res/values-tr/strings.xml b/vector/src/main/res/values-tr/strings.xml
index 91056b7193..98638c7226 100644
--- a/vector/src/main/res/values-tr/strings.xml
+++ b/vector/src/main/res/values-tr/strings.xml
@@ -126,7 +126,7 @@
Mümkünse, lütfen yapacağınız açıklamayı İngilizce yazın.Sorununu buraya yazSorunları teşhis etmek için bu istemciden gelen sistem günlüğü (log) hata raporu ile gönderilecek. Bu hata raporu -sistem günlüğü ve ekran görüntülere dahil- halka açık bir şekilde görünür olmayacaktır. Eğer sadece alttaki yazıları göndermek istiyorsanız, lütfen şunun işaretini kaldırın:
- Telefonunu öfkeyle ile sallıyor gibi görünüyorsun. Hata raporu göndermek ister misin\?
+ Telefonunu yılgınlıkla sallıyor gibi görünüyorsun. Hata raporu göndermek ister misin\?Uygulama en son çökmüştü, hata raporu göndermek ister misiniz\?Hata bildirmek için öfkeyle salla
diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml
index cac1d7bd0e..9aea75781e 100644
--- a/vector/src/main/res/values-zh-rCN/strings.xml
+++ b/vector/src/main/res/values-zh-rCN/strings.xml
@@ -5,6 +5,10 @@
zhCN
+ 接受
+ 拒绝
+ 挂断
+
重新发送引用分享
@@ -179,7 +183,7 @@
发送者的会话信息公开名称
- ID
+ 会话 ID会话密钥验证Ed25519 指纹
@@ -1794,7 +1798,7 @@ Element 在后台时的工作将被显著的限制,这可能会影响消息通
报告此内容报告此内容的理由报告
- 屏蔽用户
+ 忽略用户内容已报告此内容已报告。
@@ -1815,7 +1819,7 @@ Element 在后台时的工作将被显著的限制,这可能会影响消息通
目前没有网络连接
- 屏蔽用户
+ 忽略用户全部消息(嘈杂)全部消息
@@ -2532,4 +2536,31 @@ Element 在后台时的工作将被显著的限制,这可能会影响消息通
确认 PIN 并禁用 PIN防止意外通话发起通话之前要求确认
+ 您没有权限在此聊天室发起会议通话
+ 会议正在进行!
+ 发起视频会议
+ 发起音频会议
+ 会议使用 Jitsi 安全与许可政策。您的会议进行期间当前聊天室内的所有人将看到加入邀请。
+ 您无法呼叫您自己
+ 您无法呼叫您自己,请等待参与者接受邀请
+ 添加小部件失败
+ 移除小部件失败
+
+ 成功导入 %1$d/%2$d 个密钥。
+
+
+ 管理集成
+ 无活动小部件
+ 聊天室已创建,但由于以下原因一些邀请尚未发送:
+\n
+\n%s
+
+
+ %1$s,%2$s 和其他 %3$d 人已读
+
+
+ 错误代码,剩余 %d 次尝试
+
+ 注意!登出前最后一次尝试!
+ 错误次数过多,您已被登出
diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml
index fbf26817b8..24480a2d90 100644
--- a/vector/src/main/res/values-zh-rTW/strings.xml
+++ b/vector/src/main/res/values-zh-rTW/strings.xml
@@ -10,6 +10,10 @@
正在同步……聆聽事件
+ 接受
+ 拒絕
+ 掛斷
+
訊息聊天室設定
@@ -698,7 +702,7 @@
發送者的工作階段訊息公開名稱公開名稱
- ID
+ 工作階段 ID工作階段金鑰驗證Ed25519 指紋
@@ -1630,7 +1634,7 @@ Matrix 中的消息可見度類似于電子郵件。我們忘記您的郵件意
回報此內容回報此內容的理由回報
- 封鎖使用者
+ 忽略使用者內容已回報此內容已回報。
@@ -1689,7 +1693,7 @@ Matrix 中的消息可見度類似于電子郵件。我們忘記您的郵件意
讀取 DRM 保護的媒體這不是有效的 Matrix 伺服器位置
- 封鎖使用者
+ 忽略使用者所有訊息(吵雜)所有訊息
@@ -2516,4 +2520,31 @@ Matrix 中的消息可見度類似于電子郵件。我們忘記您的郵件意
確認 PIN 碼以停用 PIN 碼避免意外的通話開始通話前要求確認
+ 您沒有在此聊天室中開始會議通話的權限
+ 會議已在進行中!
+ 開始視訊會議
+ 開始音訊會議
+ 會議使用 Jitsi 安全與權限策略。目前在聊天室中的所有人在您的會議開始時都會看到加入的邀請。
+ 您無法與自己通話
+ 您無法與自己進行通話,請等候參與者接受邀請
+ 新增小工具失敗
+ 移除小工具失敗
+
+ %1$d/%2$d 金鑰匯入成功。
+
+
+ 管理整合
+ 無作用中的小工具
+ 已建立聊天室,但因為以下理由而未傳送某些邀請:
+\n
+\n%s
+
+
+ %1$s, %2$s 與 %3$d 個其他人已讀取
+
+
+ 錯誤的代碼,還可以嘗試 %d 次
+
+ 警告!登出前的最後一次嘗試!
+ 太多錯誤,您已被登出
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 7506a4d502..06e9530ad5 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -114,6 +114,10 @@
ReviewDecline
+ Accept
+ Decline
+ Hang Up
+
ExitActions
@@ -281,6 +285,7 @@
"This doesn’t look like a valid email address""This doesn’t look like a valid phone number"This email address is already defined.
+ This phone number is already defined.Missing email addressMissing phone numberMissing email address or phone number
@@ -675,6 +680,7 @@
EmailAdd email addressPhone
+ No phone number has been added to your accountAdd phone numberApplication infoShow the application info in the system settings.
@@ -682,6 +688,11 @@
You can\'t do this from Element mobileAuthentication is required
+ Email addresses
+ No email has been added to your account
+ Phone numbers
+ Remove %s?
+ Ensure that you have clicked on the link in the email we have sent to you.Advanced Notification SettingsNotification importance by event
@@ -927,6 +938,9 @@
Show all messages from %s?\n\nNote that this action will restart the app and it may take some time.Passwords do not match
+ Emails and phone numbers
+ Manage emails and phone numbers linked to your Matrix account
+
Are you sure you want to remove this notification target?Are you sure you want to remove the %1$s %2$s?
@@ -1756,6 +1770,7 @@
Identity server has no terms of servicesThe identity server you have chosen does not have any terms of services. Only continue if you trust the owner of the serviceA text message has been sent to %s. Please enter the verification code it contains.
+ CodeThe verification code is not correct.You are currently sharing email addresses or phone numbers on the identity server %1$s. You will need to reconnect to %2$s to stop sharing them.
@@ -1944,6 +1959,7 @@
Send againNext
+ "Please use the international format (phone number must start with '+')""International phone numbers must start with '+'""Phone number seems invalid. Please check it"
@@ -2413,8 +2429,11 @@
Verify loginInteractively Verify by EmojiConfirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.
+ Confirm your identity by verifying this login, granting it access to encrypted messages.Mark as Trusted
+ Sorry, this operation is not possible yet for accounts connected using Single Sign-On.
+
Please choose a username.Please choose a password.Double-check this link
diff --git a/vector/src/main/res/xml/vector_settings_general.xml b/vector/src/main/res/xml/vector_settings_general.xml
index 042ea5c77c..c1fe82e4c2 100644
--- a/vector/src/main/res/xml/vector_settings_general.xml
+++ b/vector/src/main/res/xml/vector_settings_general.xml
@@ -3,7 +3,6 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
-
@@ -22,29 +21,13 @@
android:summary="@string/change_password_summary"
android:title="@string/settings_password" />
-
-
-
-
-
-
-
-
+ android:key="SETTINGS_EMAILS_AND_PHONE_NUMBERS_PREFERENCE_KEY"
+ android:summary="@string/settings_emails_and_phone_numbers_summary"
+ android:title="@string/settings_emails_and_phone_numbers_title"
+ app:fragment="im.vector.app.features.settings.threepids.ThreePidsSettingsFragment" />