Merge branch 'develop' into feature/aris/threads

This commit is contained in:
ariskotsomitopoulos 2022-01-31 15:58:12 +02:00
commit d509b3324c
94 changed files with 1488 additions and 421 deletions

View file

@ -1,3 +1,15 @@
Changes in Element v1.3.17 (2022-01-31)
=======================================
Bugfixes 🐛
----------
- Display static map images in the timeline and improve Location sharing feature ([#5084](https://github.com/vector-im/element-android/issues/5084))
- Show the legal mention of mapbox when sharing location ([#5062](https://github.com/vector-im/element-android/issues/5062))
- Poll cannot end in some unencrypted rooms ([#5067](https://github.com/vector-im/element-android/issues/5067))
- Selecting Transfer in a call should immediately put the other person on hold until the call connects or the Transfer is cancelled. ([#5081](https://github.com/vector-im/element-android/issues/5081))
- Fixing crashes when quickly scrolling or restoring the room timeline ([#5091](https://github.com/vector-im/element-android/issues/5091))
Changes in Element 1.3.16 (2022-01-25) Changes in Element 1.3.16 (2022-01-25)
====================================== ======================================

View file

@ -1 +0,0 @@
Show the legal mention of mapbox when sharing location

View file

@ -1 +0,0 @@
Poll cannot end in some unencrypted rooms

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Změna na úvodních obrazovkách, včetně přihlášení do služby Analytics. V experimentálních funkcích byla přidána podpora pro události s matematikou.
Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Změna na úvodních obrazovkách, včetně přihlášení do služby Analytics. V experimentálních funkcích byla přidána podpora pro události s matematikou.
Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Změna na úvodních obrazovkách, včetně přihlášení do služby Analytics. V experimentálních funkcích byla přidána podpora pro události s matematikou.
Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Hauptänderungen: Neues Onboarding, Unterstützung für Mathematische Ausdrücke in Labs
Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Hauptänderungen: Neues Onboarding, Unterstützung für Mathematische Ausdrücke in Labs
Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Hauptänderungen: Neues Onboarding, Unterstützung für Mathematische Ausdrücke in Labs
Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Main changes in this version: send your location to any room. Edit poll.
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.17

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: liitumisvaate täiendused, võimalus saata meile analüütikat. Katsete alla on lisandunud üritused ning matemaatiliste valemite kirjutamise võimalus.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: liitumisvaate täiendused, võimalus saata meile analüütikat. Katsete alla on lisandunud üritused ning matemaatiliste valemite kirjutamise võimalus.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: liitumisvaate täiendused, võimalus saata meile analüütikat. Katsete alla on lisandunud üritused ning matemaatiliste valemite kirjutamise võimalus.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Fő változás ebben a verzióban: Első változások a bemutató képernyőn, beleértve az analitikai adatküldés engedélyezésének lehetőségét. Matematikai formulák támogatása a Laborok között.
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Fő változás ebben a verzióban: Első változások a bemutató képernyőn, beleértve az analitikai adatküldés engedélyezésének lehetőségét. Matematikai formulák támogatása a Laborok között.
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Fő változás ebben a verzióban: Első változások a bemutató képernyőn, beleértve az analitikai adatküldés engedélyezésének lehetőségét. Matematikai formulák támogatása a Laborok között.
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Perubahan pertama di layar permulaan, termasuk analitik opt-in. Dukungan untuk Peristiwa dengan Matematika ditambahkan di Uji Coba.
Changelog lanjutan:

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Perubahan pertama di layar permulaan, termasuk analitik opt-in. Dukungan untuk Peristiwa dengan Matematika ditambahkan di Uji Coba.
Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Perubahan pertama di layar permulaan, termasuk analitik opt-in. Dukungan untuk Peristiwa dengan Matematika ditambahkan di Uji Coba.
Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: prima modifica nelle schermate onboarding, incluso l'opt-in di Analytics. Supporto agli eventi con Math aggiunto nei laboratori.
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: prima modifica nelle schermate onboarding, incluso l'opt-in di Analytics. Supporto agli eventi con Math aggiunto nei laboratori.
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: prima modifica nelle schermate onboarding, incluso l'opt-in di Analytics. Supporto agli eventi con Math aggiunto nei laboratori.
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Primeira mudança em telas de onboarding, incluindo opt-in de Analítica. Suporte para Eventos com Matemática adicionado nos labs.
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Primeira mudança em telas de onboarding, incluindo opt-in de Analítica. Suporte para Eventos com Matemática adicionado nos labs.
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Primeira mudança em telas de onboarding, incluindo opt-in de Analítica. Suporte para Eventos com Matemática adicionado nos labs.
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Prvá zmena v obrazovkách pri vstupe do systému vrátane prihlásenia do služby Analytics. Pridanie podpory pre udalosti s matematikou v laboratóriách.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Prvá zmena v obrazovkách pri vstupe do systému vrátane prihlásenia do služby Analytics. Pridanie podpory pre udalosti s matematikou v laboratóriách.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Prvá zmena v obrazovkách pri vstupe do systému vrátane prihlásenia do služby Analytics. Pridanie podpory pre udalosti s matematikou v laboratóriách.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
Основні зміни у цій версії: перша зміна на екрані привітання, включно з увімкненням аналітики. У лабораторії додано підтримку подій з математичними формулами.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
Основні зміни у цій версії: перша зміна на екрані привітання, включно з увімкненням аналітики. У лабораторії додано підтримку подій з математичними формулами.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
Основні зміни у цій версії: перша зміна на екрані привітання, включно з увімкненням аналітики. У лабораторії додано підтримку подій з математичними формулами.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,2 @@
此版本中的主要變動:首次使用畫面的第一個變化,包含了選擇加入的分析功能。新增對數學活動的支援至實驗室中。
完整的變更紀錄https://github.com/vector-im/element-android/releases/tag/v1.3.13

View file

@ -0,0 +1,2 @@
此版本中的主要變動:首次使用畫面的第一個變化,包含了選擇加入的分析功能。新增對數學活動的支援至實驗室中。
完整的變更紀錄https://github.com/vector-im/element-android/releases/tag/v1.3.14

View file

@ -0,0 +1,2 @@
此版本中的主要變動:首次使用畫面的第一個變化,包含了選擇加入的分析功能。新增對數學活動的支援至實驗室中。
完整的變更紀錄https://github.com/vector-im/element-android/releases/tag/v1.3.15

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="is_rtl">true</bool>
</resources>

View file

@ -4,4 +4,6 @@
<!-- Created to detect what has to be implemented (especially in the settings) --> <!-- Created to detect what has to be implemented (especially in the settings) -->
<bool name="false_not_implemented">false</bool> <bool name="false_not_implemented">false</bool>
<bool name="is_rtl">false</bool>
</resources> </resources>

View file

@ -169,7 +169,7 @@ dependencies {
implementation libs.apache.commonsImaging implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber // Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.41' implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.42'
testImplementation libs.tests.junit testImplementation libs.tests.junit
testImplementation 'org.robolectric:robolectric:4.7.3' testImplementation 'org.robolectric:robolectric:4.7.3'

View file

@ -63,5 +63,5 @@ data class MessageLocationContent(
@Json(name = "org.matrix.msc1767.text") val text: String? = null @Json(name = "org.matrix.msc1767.text") val text: String? = null
) : MessageContent { ) : MessageContent {
fun getUri() = locationInfo?.geoUri ?: geoUri fun getBestGeoUri() = locationInfo?.geoUri ?: geoUri
} }

View file

@ -74,6 +74,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
event to it event to it
} }
} }
Timber.d("[PushRules] matched ${matchedEvents.size} out of ${allEvents.size}")
val allRedactedEvents = params.syncResponse.join val allRedactedEvents = params.syncResponse.join
.asSequence() .asSequence()

View file

@ -376,7 +376,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho:1.6.0' implementation 'com.facebook.stetho:stetho:1.6.0'
// Phone number https://github.com/google/libphonenumber // Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.41' implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.42'
// FlowBinding // FlowBinding
implementation libs.github.flowBinding implementation libs.github.flowBinding

View file

@ -195,6 +195,9 @@ fun activityIdlingResource(activityClass: Class<*>): IdlingResource {
println("*** [$name] onActivityLifecycleChanged callback: $callback") println("*** [$name] onActivityLifecycleChanged callback: $callback")
callback?.onTransitionToIdle() callback?.onTransitionToIdle()
} }
else -> {
// do nothing, we're blocking until the activity resumes
}
} }
} }
} }

View file

@ -17,12 +17,16 @@
package im.vector.app.ui.robot package im.vector.app.ui.robot
import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import im.vector.app.R import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
import im.vector.app.features.reactions.EmojiReactionPickerActivity
import im.vector.app.interactWithSheet import im.vector.app.interactWithSheet
import java.lang.Thread.sleep import java.lang.Thread.sleep
@ -54,7 +58,10 @@ class MessageMenuRobot(
fun addReactionFromEmojiPicker() { fun addReactionFromEmojiPicker() {
clickOn(R.string.message_add_reaction) clickOn(R.string.message_add_reaction)
// Wait for emoji to load, it's async now // Wait for emoji to load, it's async now
sleep(2000) waitUntilActivityVisible<EmojiReactionPickerActivity> {
waitUntilViewVisible(withId(R.id.emojiRecyclerView))
waitUntilViewVisible(withText("😀"))
}
clickListItem(R.id.emojiRecyclerView, 4) clickListItem(R.id.emojiRecyclerView, 4)
autoClosed = true autoClosed = true
} }

View file

@ -20,13 +20,13 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import com.adevinta.android.barista.interaction.BaristaClickInteractions import com.adevinta.android.barista.interaction.BaristaClickInteractions
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaClickInteractions.longClickOn
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.clickMenu import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.clickMenu
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu
@ -70,6 +70,7 @@ class RoomDetailRobot {
openMessageMenu(message) { openMessageMenu(message) {
addQuickReaction(quickReaction) addQuickReaction(quickReaction)
} }
waitUntilViewVisible(withText(quickReaction))
println("Open reactions bottom sheet") println("Open reactions bottom sheet")
// Open reactions // Open reactions
longClickReaction(quickReaction) longClickReaction(quickReaction)
@ -103,7 +104,7 @@ class RoomDetailRobot {
private fun longClickReaction(quickReaction: String) { private fun longClickReaction(quickReaction: String) {
withRetry { withRetry {
longClickOn(quickReaction) onView(withText(quickReaction)).perform(longClick())
} }
} }

View file

@ -17,24 +17,25 @@
package im.vector.app.core.epoxy.bottomsheet package im.vector.app.core.epoxy.bottomsheet
import android.text.method.MovementMethod import android.text.method.MovementMethod
import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.bumptech.glide.request.RequestOptions
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.glide.GlideApp
import im.vector.app.features.displayname.getBestName import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.item.BindingOptions
import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess
import im.vector.app.features.location.LocationData
import im.vector.app.features.location.MapTilerMapView
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
@ -70,7 +71,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
var time: String? = null var time: String? = null
@EpoxyAttribute @EpoxyAttribute
var locationData: LocationData? = null var locationUrl: String? = null
@EpoxyAttribute @EpoxyAttribute
var locationPinProvider: LocationPinProvider? = null var locationPinProvider: LocationPinProvider? = null
@ -97,17 +98,21 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
body.charSequence.findPillsAndProcess(coroutineScope) { it.bind(holder.body) } body.charSequence.findPillsAndProcess(coroutineScope) { it.bind(holder.body) }
holder.timestamp.setTextOrHide(time) holder.timestamp.setTextOrHide(time)
holder.mapView.isVisible = locationData != null if (locationUrl == null) {
holder.body.isVisible = locationData == null holder.body.isVisible = true
locationData?.let { location -> holder.mapViewContainer.isVisible = false
holder.mapView.initialize { } else {
if (holder.view.isAttachedToWindow) { holder.body.isVisible = false
holder.mapView.zoomToLocation(location.latitude, location.longitude, 15.0) holder.mapViewContainer.isVisible = true
GlideApp.with(holder.staticMapImageView)
.load(locationUrl)
.apply(RequestOptions.centerCropTransform())
.into(holder.staticMapImageView)
locationPinProvider?.create(matrixItem.id) { pinDrawable -> locationPinProvider?.create(matrixItem.id) { pinDrawable ->
holder.mapView.addPinToMap(matrixItem.id, pinDrawable) GlideApp.with(holder.staticMapPinImageView)
holder.mapView.updatePinLocation(matrixItem.id, location.latitude, location.longitude) .load(pinDrawable)
} .into(holder.staticMapPinImageView)
}
} }
} }
} }
@ -124,6 +129,8 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
val bodyDetails by bind<TextView>(R.id.bottom_sheet_message_preview_body_details) val bodyDetails by bind<TextView>(R.id.bottom_sheet_message_preview_body_details)
val timestamp by bind<TextView>(R.id.bottom_sheet_message_preview_timestamp) val timestamp by bind<TextView>(R.id.bottom_sheet_message_preview_timestamp)
val imagePreview by bind<ImageView>(R.id.bottom_sheet_message_preview_image) val imagePreview by bind<ImageView>(R.id.bottom_sheet_message_preview_image)
val mapView by bind<MapTilerMapView>(R.id.bottom_sheet_message_preview_location) val mapViewContainer by bind<FrameLayout>(R.id.mapViewContainer)
val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
} }
} }

View file

@ -46,12 +46,14 @@ data class PerformanceTimer(
enum class Name { enum class Name {
/** /**
* The time spent parsing the response from an initial /sync request. * The time spent parsing the response from an initial /sync request. In
* this case, `itemCount` should contain the number of joined rooms.
*/ */
InitialSyncParsing, InitialSyncParsing,
/** /**
* The time spent waiting for a response to an initial /sync request. * The time spent waiting for a response to an initial /sync request. In
* this case, `itemCount` should contain the number of joined rooms.
*/ */
InitialSyncRequest, InitialSyncRequest,
@ -62,13 +64,16 @@ data class PerformanceTimer(
NotificationsOpenEvent, NotificationsOpenEvent,
/** /**
* The duration of a regular /sync request when resuming the app. * The duration of a regular /sync request when resuming the app. In
* this case, `itemCount` should contain the number of joined rooms in
* the response.
*/ */
StartupIncrementalSync, StartupIncrementalSync,
/** /**
* The duration of an initial /sync request during startup (if the store * The duration of an initial /sync request during startup (if the store
* has been wiped). * has been wiped). In this case, `itemCount` should contain the number
* of joined rooms.
*/ */
StartupInitialSync, StartupInitialSync,

View file

@ -16,6 +16,7 @@
package im.vector.app.features.call package im.vector.app.features.call
import android.app.Activity
import android.app.KeyguardManager import android.app.KeyguardManager
import android.app.PictureInPictureParams import android.app.PictureInPictureParams
import android.content.Context import android.content.Context
@ -43,6 +44,7 @@ import com.google.android.material.card.MaterialCardView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
@ -518,13 +520,19 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
} }
is VectorCallViewEvents.ShowCallTransferScreen -> { is VectorCallViewEvents.ShowCallTransferScreen -> {
val callId = withState(callViewModel) { it.callId } val callId = withState(callViewModel) { it.callId }
navigator.openCallTransfer(this, callId) navigator.openCallTransfer(this, callTransferActivityResultLauncher, callId)
} }
null -> { null -> {
} }
} }
} }
private val callTransferActivityResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_CANCELED) {
callViewModel.handle(VectorCallViewActions.CallTransferSelectionCancelled)
}
}
private fun onErrorTimoutConnect(turn: TurnServerResponse?) { private fun onErrorTimoutConnect(turn: TurnServerResponse?) {
Timber.tag(loggerTag.value).d("onErrorTimoutConnect $turn") Timber.tag(loggerTag.value).d("onErrorTimoutConnect $turn")
// TODO ask to use default stun, etc... // TODO ask to use default stun, etc...

View file

@ -36,5 +36,6 @@ sealed class VectorCallViewActions : VectorViewModelAction {
object ToggleCamera : VectorCallViewActions() object ToggleCamera : VectorCallViewActions()
object ToggleHDSD : VectorCallViewActions() object ToggleHDSD : VectorCallViewActions()
object InitiateCallTransfer : VectorCallViewActions() object InitiateCallTransfer : VectorCallViewActions()
object CallTransferSelectionCancelled : VectorCallViewActions()
object TransferCall : VectorCallViewActions() object TransferCall : VectorCallViewActions()
} }

View file

@ -319,10 +319,14 @@ class VectorCallViewModel @AssistedInject constructor(
call?.sendDtmfDigit(action.digit) call?.sendDtmfDigit(action.digit)
} }
VectorCallViewActions.InitiateCallTransfer -> { VectorCallViewActions.InitiateCallTransfer -> {
call?.updateRemoteOnHold(true)
_viewEvents.post( _viewEvents.post(
VectorCallViewEvents.ShowCallTransferScreen VectorCallViewEvents.ShowCallTransferScreen
) )
} }
VectorCallViewActions.CallTransferSelectionCancelled -> {
call?.updateRemoteOnHold(false)
}
VectorCallViewActions.TransferCall -> { VectorCallViewActions.TransferCall -> {
handleCallTransfer() handleCallTransfer()
} }

View file

@ -16,6 +16,7 @@
package im.vector.app.features.call.transfer package im.vector.app.features.call.transfer
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
@ -55,7 +56,7 @@ class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>() {
callTransferViewModel.observeViewEvents { callTransferViewModel.observeViewEvents {
when (it) { when (it) {
is CallTransferViewEvents.Dismiss -> finish() is CallTransferViewEvents.Complete -> handleComplete()
CallTransferViewEvents.Loading -> showWaitingView() CallTransferViewEvents.Loading -> showWaitingView()
is CallTransferViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure)) is CallTransferViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure))
} }
@ -93,6 +94,11 @@ class CallTransferActivity : VectorBaseActivity<ActivityCallTransferBinding>() {
} }
} }
private fun handleComplete() {
setResult(Activity.RESULT_OK)
finish()
}
companion object { companion object {
fun newIntent(context: Context, callId: String): Intent { fun newIntent(context: Context, callId: String): Intent {

View file

@ -19,7 +19,7 @@ package im.vector.app.features.call.transfer
import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewEvents
sealed class CallTransferViewEvents : VectorViewEvents { sealed class CallTransferViewEvents : VectorViewEvents {
object Dismiss : CallTransferViewEvents() object Complete : CallTransferViewEvents()
object Loading : CallTransferViewEvents() object Loading : CallTransferViewEvents()
object FailToTransfer : CallTransferViewEvents() object FailToTransfer : CallTransferViewEvents()
} }

View file

@ -50,14 +50,14 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
private val callListener = object : WebRtcCall.Listener { private val callListener = object : WebRtcCall.Listener {
override fun onStateUpdate(call: MxCall) { override fun onStateUpdate(call: MxCall) {
if (call.state is CallState.Ended) { if (call.state is CallState.Ended) {
_viewEvents.post(CallTransferViewEvents.Dismiss) _viewEvents.post(CallTransferViewEvents.Complete)
} }
} }
} }
init { init {
if (call == null) { if (call == null) {
_viewEvents.post(CallTransferViewEvents.Dismiss) _viewEvents.post(CallTransferViewEvents.Complete)
} else { } else {
call.addListener(callListener) call.addListener(callListener)
} }
@ -89,7 +89,7 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
} else { } else {
call?.transferToUser(action.selectedUserId, null) call?.transferToUser(action.selectedUserId, null)
} }
_viewEvents.post(CallTransferViewEvents.Dismiss) _viewEvents.post(CallTransferViewEvents.Complete)
} catch (failure: Throwable) { } catch (failure: Throwable) {
_viewEvents.post(CallTransferViewEvents.FailToTransfer) _viewEvents.post(CallTransferViewEvents.FailToTransfer)
} }
@ -111,7 +111,7 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
} else { } else {
call?.transferToUser(result.userId, result.roomId) call?.transferToUser(result.userId, result.roomId)
} }
_viewEvents.post(CallTransferViewEvents.Dismiss) _viewEvents.post(CallTransferViewEvents.Complete)
} catch (failure: Throwable) { } catch (failure: Throwable) {
_viewEvents.post(CallTransferViewEvents.FailToTransfer) _viewEvents.post(CallTransferViewEvents.FailToTransfer)
} }

View file

@ -20,7 +20,6 @@ import android.net.Uri
import android.view.View import android.view.View
import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.platform.VectorViewModelAction
import im.vector.app.features.call.conference.ConferenceEvent import im.vector.app.features.call.conference.ConferenceEvent
import im.vector.app.features.location.LocationData
import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
@ -90,6 +89,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
data class EnsureNativeWidgetAllowed(val widget: Widget, data class EnsureNativeWidgetAllowed(val widget: Widget,
val userJustAccepted: Boolean, val userJustAccepted: Boolean,
val grantedEvents: RoomDetailViewEvents) : RoomDetailAction() val grantedEvents: RoomDetailViewEvents) : RoomDetailAction()
data class UpdateJoinJitsiCallStatus(val conferenceEvent: ConferenceEvent) : RoomDetailAction() data class UpdateJoinJitsiCallStatus(val conferenceEvent: ConferenceEvent) : RoomDetailAction()
data class OpenOrCreateDm(val userId: String) : RoomDetailAction() data class OpenOrCreateDm(val userId: String) : RoomDetailAction()
@ -112,7 +112,4 @@ sealed class RoomDetailAction : VectorViewModelAction {
// Poll // Poll
data class EndPoll(val eventId: String) : RoomDetailAction() data class EndPoll(val eventId: String) : RoomDetailAction()
// Location
data class ShowLocation(val locationData: LocationData, val userId: String) : RoomDetailAction()
} }

View file

@ -20,7 +20,6 @@ import android.net.Uri
import android.view.View import android.view.View
import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.features.call.webrtc.WebRtcCall import im.vector.app.features.call.webrtc.WebRtcCall
import im.vector.app.features.location.LocationData
import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.session.widgets.model.Widget
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
@ -83,6 +82,4 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
data class StartChatEffect(val type: ChatEffect) : RoomDetailViewEvents() data class StartChatEffect(val type: ChatEffect) : RoomDetailViewEvents()
object StopChatEffects : RoomDetailViewEvents() object StopChatEffects : RoomDetailViewEvents()
object RoomReplacementStarted : RoomDetailViewEvents() object RoomReplacementStarted : RoomDetailViewEvents()
data class ShowLocation(val locationData: LocationData, val userId: String) : RoomDetailViewEvents()
} }

View file

@ -174,8 +174,8 @@ import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.PillImageSpan import im.vector.app.features.html.PillImageSpan
import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.PillsPostProcessor
import im.vector.app.features.invite.VectorInviteView import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.location.LocationData
import im.vector.app.features.location.LocationSharingMode import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.NotificationDrawerManager
@ -478,7 +478,6 @@ class TimelineFragment @Inject constructor(
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects() RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it) is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement() RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement()
is RoomDetailViewEvents.ShowLocation -> handleShowLocationPreview(it)
}.exhaustive }.exhaustive
} }
@ -610,14 +609,14 @@ class TimelineFragment @Inject constructor(
} }
} }
private fun handleShowLocationPreview(viewEvent: RoomDetailViewEvents.ShowLocation) { private fun handleShowLocationPreview(locationContent: MessageLocationContent, senderId: String) {
navigator navigator
.openLocationSharing( .openLocationSharing(
context = requireContext(), context = requireContext(),
roomId = timelineArgs.roomId, roomId = timelineArgs.roomId,
mode = LocationSharingMode.PREVIEW, mode = LocationSharingMode.PREVIEW,
initialLocationData = viewEvent.locationData, initialLocationData = locationContent.toLocationData(),
locationOwnerId = viewEvent.userId locationOwnerId = senderId
) )
} }
@ -1934,6 +1933,12 @@ class TimelineFragment @Inject constructor(
else -> { else -> {
onThreadSummaryClicked(informationData.eventId, isRootThreadEvent) onThreadSummaryClicked(informationData.eventId, isRootThreadEvent)
} }
is MessageLocationContent -> {
handleShowLocationPreview(messageContent, informationData.senderId)
}
else -> {
Timber.d("No click action defined for this message content")
}
} }
} }
@ -2052,7 +2057,7 @@ class TimelineFragment @Inject constructor(
when (action.messageContent) { when (action.messageContent) {
is MessageTextContent -> shareText(requireContext(), action.messageContent.body) is MessageTextContent -> shareText(requireContext(), action.messageContent.body)
is MessageLocationContent -> { is MessageLocationContent -> {
LocationData.create(action.messageContent.getUri())?.let { action.messageContent.toLocationData()?.let {
openLocation(requireActivity(), it.latitude, it.longitude) openLocation(requireActivity(), it.latitude, it.longitude)
} }
} }

View file

@ -53,7 +53,6 @@ import im.vector.app.features.home.room.detail.sticker.StickerPickerActionHandle
import im.vector.app.features.home.room.detail.timeline.factory.TimelineFactory import im.vector.app.features.home.room.detail.timeline.factory.TimelineFactory
import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever
import im.vector.app.features.home.room.typing.TypingHelper import im.vector.app.features.home.room.typing.TypingHelper
import im.vector.app.features.location.LocationData
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import im.vector.app.features.session.coroutineScope import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorDataStore import im.vector.app.features.settings.VectorDataStore
@ -432,14 +431,9 @@ class TimelineViewModel @AssistedInject constructor(
_viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true)) _viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true))
} }
is RoomDetailAction.EndPoll -> handleEndPoll(action.eventId) is RoomDetailAction.EndPoll -> handleEndPoll(action.eventId)
is RoomDetailAction.ShowLocation -> handleShowLocation(action.locationData, action.userId)
}.exhaustive }.exhaustive
} }
private fun handleShowLocation(locationData: LocationData, userId: String) {
_viewEvents.post(RoomDetailViewEvents.ShowLocation(locationData, userId))
}
private fun handleJitsiCallJoinStatus(action: RoomDetailAction.UpdateJoinJitsiCallStatus) = withState { state -> private fun handleJitsiCallJoinStatus(action: RoomDetailAction.UpdateJoinJitsiCallStatus) = withState { state ->
if (state.jitsiState.confId == null) { if (state.jitsiState.confId == null) {
// If jitsi widget is removed while on the call // If jitsi widget is removed while on the call

View file

@ -39,7 +39,9 @@ import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
import im.vector.app.features.home.room.detail.timeline.tools.linkify import im.vector.app.features.home.room.detail.timeline.tools.linkify
import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.SpanUtils
import im.vector.app.features.location.LocationData import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
@ -62,6 +64,7 @@ class MessageActionsEpoxyController @Inject constructor(
private val spanUtils: SpanUtils, private val spanUtils: SpanUtils,
private val eventDetailsFormatter: EventDetailsFormatter, private val eventDetailsFormatter: EventDetailsFormatter,
private val dateFormatter: VectorDateFormatter, private val dateFormatter: VectorDateFormatter,
private val urlMapProvider: UrlMapProvider,
private val locationPinProvider: LocationPinProvider private val locationPinProvider: LocationPinProvider
) : TypedEpoxyController<MessageActionState>() { ) : TypedEpoxyController<MessageActionState>() {
@ -74,9 +77,11 @@ class MessageActionsEpoxyController @Inject constructor(
val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL) val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL)
val body = state.messageBody.linkify(host.listener) val body = state.messageBody.linkify(host.listener)
val bindingOptions = spanUtils.getBindingOptions(body) val bindingOptions = spanUtils.getBindingOptions(body)
val locationData = state.timelineEvent()?.root?.getClearContent()?.toModel<MessageLocationContent>(catchError = true)?.let { val locationUrl = state.timelineEvent()?.root?.getClearContent()
LocationData.create(it.getUri()) ?.toModel<MessageLocationContent>(catchError = true)
} ?.toLocationData()
?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) }
bottomSheetMessagePreviewItem { bottomSheetMessagePreviewItem {
id("preview") id("preview")
avatarRenderer(host.avatarRenderer) avatarRenderer(host.avatarRenderer)
@ -89,7 +94,7 @@ class MessageActionsEpoxyController @Inject constructor(
body(body.toEpoxyCharSequence()) body(body.toEpoxyCharSequence())
bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)?.toEpoxyCharSequence()) bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)?.toEpoxyCharSequence())
time(formattedDate) time(formattedDate)
locationData(locationData) locationUrl(locationUrl)
locationPinProvider(host.locationPinProvider) locationPinProvider(host.locationPinProvider)
} }

View file

@ -16,6 +16,7 @@
package im.vector.app.features.home.room.detail.timeline.factory package im.vector.app.features.home.room.detail.timeline.factory
import android.content.res.Resources
import android.text.Spannable import android.text.Spannable
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
@ -33,7 +34,6 @@ import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.DimensionConverter
import im.vector.app.core.utils.containsOnlyEmojis import im.vector.app.core.utils.containsOnlyEmojis
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
@ -71,7 +71,9 @@ import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.PillsPostProcessor
import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.SpanUtils
import im.vector.app.features.html.VectorHtmlCompressor import im.vector.app.features.html.VectorHtmlCompressor
import im.vector.app.features.location.LocationData import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
@ -127,7 +129,10 @@ class MessageItemFactory @Inject constructor(
private val session: Session, private val session: Session,
private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker, private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
private val locationPinProvider: LocationPinProvider, private val locationPinProvider: LocationPinProvider,
private val vectorPreferences: VectorPreferences) { private val vectorPreferences: VectorPreferences,
private val urlMapProvider: UrlMapProvider,
private val resources: Resources
) {
// TODO inject this properly? // TODO inject this properly?
private var roomId: String = "" private var roomId: String = ""
@ -186,7 +191,7 @@ class MessageItemFactory @Inject constructor(
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes) is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
is MessageLocationContent -> { is MessageLocationContent -> {
if (vectorPreferences.labsRenderLocationsInTimeline()) { if (vectorPreferences.labsRenderLocationsInTimeline()) {
buildLocationItem(messageContent, informationData, highlight, callback, attributes) buildLocationItem(messageContent, informationData, highlight, attributes)
} else { } else {
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes) buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
} }
@ -202,27 +207,21 @@ class MessageItemFactory @Inject constructor(
private fun buildLocationItem(locationContent: MessageLocationContent, private fun buildLocationItem(locationContent: MessageLocationContent,
informationData: MessageInformationData, informationData: MessageInformationData,
highlight: Boolean, highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes): MessageLocationItem? { attributes: AbsMessageItem.Attributes): MessageLocationItem? {
val geoUri = locationContent.getUri() val width = resources.displayMetrics.widthPixels - dimensionConverter.dpToPx(60)
val locationData = LocationData.create(geoUri) val height = dimensionConverter.dpToPx(200)
val mapCallback: MessageLocationItem.Callback = object : MessageLocationItem.Callback { val locationUrl = locationContent.toLocationData()?.let {
override fun onMapClicked() { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height)
locationData?.let {
callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(it, informationData.senderId))
}
}
} }
return MessageLocationItem_() return MessageLocationItem_()
.attributes(attributes) .attributes(attributes)
.locationData(locationData) .locationUrl(locationUrl)
.userId(informationData.senderId) .userId(informationData.senderId)
.locationPinProvider(locationPinProvider) .locationPinProvider(locationPinProvider)
.highlighted(highlight) .highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline) .leftGuideline(avatarSizeProvider.leftGuideline)
.callback(mapCallback)
} }
private fun buildPollItem(pollContent: MessagePollContent, private fun buildPollItem(pollContent: MessagePollContent,

View file

@ -28,6 +28,7 @@ import im.vector.app.core.glide.GlideApp
import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.api.util.toMatrixItem
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -54,22 +55,36 @@ class LocationPinProvider @Inject constructor(
val size = dimensionConverter.dpToPx(44) val size = dimensionConverter.dpToPx(44)
avatarRenderer.render(glideRequests, it, object : CustomTarget<Drawable>(size, size) { avatarRenderer.render(glideRequests, it, object : CustomTarget<Drawable>(size, size) {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) { override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
val bgUserPin = ContextCompat.getDrawable(context, R.drawable.bg_map_user_pin)!! Timber.d("## Location: onResourceReady")
val layerDrawable = LayerDrawable(arrayOf(bgUserPin, resource)) val pinDrawable = createPinDrawable(resource)
val horizontalInset = dimensionConverter.dpToPx(4) cache[userId] = pinDrawable
val topInset = dimensionConverter.dpToPx(4) callback(pinDrawable)
val bottomInset = dimensionConverter.dpToPx(8)
layerDrawable.setLayerInset(1, horizontalInset, topInset, horizontalInset, bottomInset)
cache[userId] = layerDrawable
callback(layerDrawable)
} }
override fun onLoadCleared(placeholder: Drawable?) { override fun onLoadCleared(placeholder: Drawable?) {
// Is it possible? Put placeholder instead? // Is it possible? Put placeholder instead?
// FIXME The doc says it has to be implemented and should free resources
Timber.d("## Location: onLoadCleared")
}
override fun onLoadFailed(errorDrawable: Drawable?) {
Timber.w("## Location: onLoadFailed")
errorDrawable ?: return
val pinDrawable = createPinDrawable(errorDrawable)
cache[userId] = pinDrawable
callback(pinDrawable)
} }
}) })
} }
} }
private fun createPinDrawable(drawable: Drawable): Drawable {
val bgUserPin = ContextCompat.getDrawable(context, R.drawable.bg_map_user_pin)!!
val layerDrawable = LayerDrawable(arrayOf(bgUserPin, drawable))
val horizontalInset = dimensionConverter.dpToPx(4)
val topInset = dimensionConverter.dpToPx(4)
val bottomInset = dimensionConverter.dpToPx(8)
layerDrawable.setLayerInset(1, horizontalInset, topInset, horizontalInset, bottomInset)
return layerDrawable
}
} }

View file

@ -16,28 +16,19 @@
package im.vector.app.features.home.room.detail.timeline.item package im.vector.app.features.home.room.detail.timeline.item
import android.widget.FrameLayout import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import com.bumptech.glide.request.RequestOptions
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.onClick import im.vector.app.core.glide.GlideApp
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.location.LocationData
import im.vector.app.features.location.MapTilerMapView
@EpoxyModelClass(layout = R.layout.item_timeline_event_base) @EpoxyModelClass(layout = R.layout.item_timeline_event_base)
abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>() { abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>() {
interface Callback {
fun onMapClicked()
}
@EpoxyAttribute @EpoxyAttribute
var callback: Callback? = null var locationUrl: String? = null
@EpoxyAttribute
var locationData: LocationData? = null
@EpoxyAttribute @EpoxyAttribute
var userId: String? = null var userId: String? = null
@ -47,37 +38,31 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
override fun bind(holder: Holder) { override fun bind(holder: Holder) {
super.bind(holder) super.bind(holder)
renderSendState(holder.mapViewContainer, null) renderSendState(holder.view, null)
val location = locationData ?: return val location = locationUrl ?: return
val locationOwnerId = userId ?: return val locationOwnerId = userId ?: return
holder.clickableMapArea.onClick { GlideApp.with(holder.staticMapImageView)
callback?.onMapClicked() .load(location)
} .apply(RequestOptions.centerCropTransform())
.into(holder.staticMapImageView)
holder.mapView.apply {
initialize {
zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM)
locationPinProvider?.create(locationOwnerId) { pinDrawable -> locationPinProvider?.create(locationOwnerId) { pinDrawable ->
addPinToMap(locationOwnerId, pinDrawable) GlideApp.with(holder.staticMapPinImageView)
updatePinLocation(locationOwnerId, location.latitude, location.longitude) .load(pinDrawable)
} .into(holder.staticMapPinImageView)
}
} }
} }
override fun getViewType() = STUB_ID override fun getViewType() = STUB_ID
class Holder : AbsMessageItem.Holder(STUB_ID) { class Holder : AbsMessageItem.Holder(STUB_ID) {
val mapViewContainer by bind<ConstraintLayout>(R.id.mapViewContainer) val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
val mapView by bind<MapTilerMapView>(R.id.mapView) val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
val clickableMapArea by bind<FrameLayout>(R.id.clickableMapArea)
} }
companion object { companion object {
private const val STUB_ID = R.id.messageContentLocationStub private const val STUB_ID = R.id.messageContentLocationStub
private const val INITIAL_ZOOM = 15.0
} }
} }

View file

@ -109,6 +109,7 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
val textFuture = PrecomputedTextCompat.getTextFuture(message, TextViewCompat.getTextMetricsParams(this), null) val textFuture = PrecomputedTextCompat.getTextFuture(message, TextViewCompat.getTextMetricsParams(this), null)
setTextFuture(textFuture) setTextFuture(textFuture)
} else { } else {
setTextFuture(null)
text = message text = message
} }
} }

View file

@ -16,6 +16,10 @@
package im.vector.app.features.location package im.vector.app.features.location
const val INITIAL_MAP_ZOOM = 15.0 const val MAP_BASE_URL = "https://api.maptiler.com/maps/streets/style.json"
const val MIN_TIME_MILLIS_TO_UPDATE_LOCATION = 1 * 60 * 1000L // every 1 minute const val STATIC_MAP_BASE_URL = "https://api.maptiler.com/maps/basic/static/"
const val MIN_DISTANCE_METERS_TO_UPDATE_LOCATION = 10f
const val INITIAL_MAP_ZOOM_IN_PREVIEW = 15.0
const val INITIAL_MAP_ZOOM_IN_TIMELINE = 17.0
const val MIN_TIME_TO_UPDATE_LOCATION_MILLIS = 5 * 1_000L // every 5 seconds
const val MIN_DISTANCE_TO_UPDATE_LOCATION_METERS = 10f

View file

@ -17,41 +17,43 @@
package im.vector.app.features.location package im.vector.app.features.location
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.VisibleForTesting
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
@Parcelize @Parcelize
data class LocationData( data class LocationData(
val latitude: Double, val latitude: Double,
val longitude: Double, val longitude: Double,
val uncertainty: Double? val uncertainty: Double?
) : Parcelable { ) : Parcelable
companion object {
/** /**
* Creates location data from geo uri * Creates location data from a LocationContent
* @param geoUri geo:latitude,longitude;uncertainty * "geo:40.05,29.24;30" -> LocationData(40.05, 29.24, 30)
* @return location data or null if geo uri is not valid * @return location data or null if geo uri is not valid
*/ */
fun create(geoUri: String): LocationData? { fun MessageLocationContent.toLocationData(): LocationData? {
val geoParts = geoUri return parseGeo(getBestGeoUri())
}
@VisibleForTesting
fun parseGeo(geo: String): LocationData? {
val geoParts = geo
.split(":") .split(":")
.takeIf { it.firstOrNull() == "geo" } .takeIf { it.firstOrNull() == "geo" }
?.getOrNull(1) ?.getOrNull(1)
?.split(",") ?.split(";") ?: return null
val latitude = geoParts?.firstOrNull() val gpsParts = geoParts.getOrNull(0)?.split(",") ?: return null
val geoTailParts = geoParts?.getOrNull(1)?.split(";") val lat = gpsParts.getOrNull(0)?.toDoubleOrNull() ?: return null
val longitude = geoTailParts?.firstOrNull() val lng = gpsParts.getOrNull(1)?.toDoubleOrNull() ?: return null
val uncertainty = geoTailParts?.getOrNull(1)?.replace("u=", "")
return if (latitude != null && longitude != null) { val uncertainty = geoParts.getOrNull(1)?.replace("u=", "")?.toDoubleOrNull()
LocationData(
latitude = latitude.toDouble(), return LocationData(
longitude = longitude.toDouble(), latitude = lat,
uncertainty = uncertainty?.toDouble() longitude = lng,
uncertainty = uncertainty
) )
} else null
}
}
} }

View file

@ -21,20 +21,30 @@ import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.args import com.airbnb.mvrx.args
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.openLocation import im.vector.app.core.utils.openLocation
import im.vector.app.databinding.FragmentLocationPreviewBinding import im.vector.app.databinding.FragmentLocationPreviewBinding
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import java.lang.ref.WeakReference
import javax.inject.Inject import javax.inject.Inject
/**
* TODO Move locationPinProvider to a ViewModel
*/
class LocationPreviewFragment @Inject constructor( class LocationPreviewFragment @Inject constructor(
private val urlMapProvider: UrlMapProvider,
private val locationPinProvider: LocationPinProvider private val locationPinProvider: LocationPinProvider
) : VectorBaseFragment<FragmentLocationPreviewBinding>() { ) : VectorBaseFragment<FragmentLocationPreviewBinding>() {
private val args: LocationSharingArgs by args() private val args: LocationSharingArgs by args()
// Keep a ref to handle properly the onDestroy callback
private var mapView: WeakReference<MapView>? = null
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding {
return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false) return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false)
} }
@ -42,11 +52,15 @@ class LocationPreviewFragment @Inject constructor(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
views.mapView.initialize { mapView = WeakReference(views.mapView)
if (isAdded) { views.mapView.onCreate(savedInstanceState)
onMapReady() views.mapView.initialize(urlMapProvider.mapUrl)
} loadPinDrawable()
} }
override fun onResume() {
super.onResume()
views.mapView.onResume()
} }
override fun onPause() { override fun onPause() {
@ -54,11 +68,32 @@ class LocationPreviewFragment @Inject constructor(
super.onPause() super.onPause()
} }
override fun onLowMemory() {
views.mapView.onLowMemory()
super.onLowMemory()
}
override fun onStart() {
super.onStart()
views.mapView.onStart()
}
override fun onStop() { override fun onStop() {
views.mapView.onStop() views.mapView.onStop()
super.onStop() super.onStop()
} }
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
views.mapView.onSaveInstanceState(outState)
}
override fun onDestroy() {
mapView?.get()?.onDestroy()
mapView?.clear()
super.onDestroy()
}
override fun getMenuRes() = R.menu.menu_location_preview override fun getMenuRes() = R.menu.menu_location_preview
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -76,18 +111,20 @@ class LocationPreviewFragment @Inject constructor(
openLocation(requireActivity(), location.latitude, location.longitude) openLocation(requireActivity(), location.latitude, location.longitude)
} }
private fun onMapReady() { private fun loadPinDrawable() {
if (!isAdded) return
val location = args.initialLocationData ?: return val location = args.initialLocationData ?: return
val userId = args.locationOwnerId val userId = args.locationOwnerId
locationPinProvider.create(userId) { pinDrawable -> locationPinProvider.create(userId) { pinDrawable ->
views.mapView.apply { lifecycleScope.launchWhenResumed {
zoomToLocation(location.latitude, location.longitude, INITIAL_MAP_ZOOM) views.mapView.render(
deleteAllPins() MapState(
addPinToMap(userId, pinDrawable) zoomOnlyOnce = true,
updatePinLocation(userId, location.latitude, location.longitude) pinLocationData = location,
pinId = args.locationOwnerId,
pinDrawable = pinDrawable
)
)
} }
} }
} }

View file

@ -19,7 +19,5 @@ package im.vector.app.features.location
import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.platform.VectorViewModelAction
sealed class LocationSharingAction : VectorViewModelAction { sealed class LocationSharingAction : VectorViewModelAction {
data class OnLocationUpdate(val locationData: LocationData) : LocationSharingAction()
object OnShareLocation : LocationSharingAction() object OnShareLocation : LocationSharingAction()
object OnLocationProviderIsNotAvailable : LocationSharingAction()
} }

View file

@ -20,29 +20,29 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isGone
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentLocationSharingBinding import im.vector.app.databinding.FragmentLocationSharingBinding
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import java.lang.ref.WeakReference
import org.matrix.android.sdk.api.session.Session
import javax.inject.Inject import javax.inject.Inject
/**
* We should consider using SupportMapFragment for a out of the box lifecycle handling
*/
class LocationSharingFragment @Inject constructor( class LocationSharingFragment @Inject constructor(
private val locationTracker: LocationTracker, private val urlMapProvider: UrlMapProvider
private val session: Session, ) : VectorBaseFragment<FragmentLocationSharingBinding>() {
private val locationPinProvider: LocationPinProvider
) : VectorBaseFragment<FragmentLocationSharingBinding>(), LocationTracker.Callback {
init {
locationTracker.callback = this
}
private val viewModel: LocationSharingViewModel by fragmentViewModel() private val viewModel: LocationSharingViewModel by fragmentViewModel()
private var lastZoomValue: Double = -1.0 // Keep a ref to handle properly the onDestroy callback
private var mapView: WeakReference<MapView>? = null
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding {
return FragmentLocationSharingBinding.inflate(inflater, container, false) return FragmentLocationSharingBinding.inflate(inflater, container, false)
@ -51,11 +51,9 @@ class LocationSharingFragment @Inject constructor(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
views.mapView.initialize { mapView = WeakReference(views.mapView)
if (isAdded) { views.mapView.onCreate(savedInstanceState)
onMapReady() views.mapView.initialize(urlMapProvider.mapUrl)
}
}
views.shareLocationContainer.debouncedClicks { views.shareLocationContainer.debouncedClicks {
viewModel.handle(LocationSharingAction.OnShareLocation) viewModel.handle(LocationSharingAction.OnShareLocation)
@ -69,48 +67,42 @@ class LocationSharingFragment @Inject constructor(
} }
} }
override fun onResume() {
super.onResume()
views.mapView.onResume()
}
override fun onPause() { override fun onPause() {
views.mapView.onPause() views.mapView.onPause()
super.onPause() super.onPause()
} }
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
views.mapView.onSaveInstanceState(outState)
}
override fun onStart() {
super.onStart()
views.mapView.onStart()
}
override fun onStop() { override fun onStop() {
views.mapView.onStop() views.mapView.onStop()
super.onStop() super.onStop()
} }
override fun onLowMemory() {
super.onLowMemory()
views.mapView.onLowMemory()
}
override fun onDestroy() { override fun onDestroy() {
locationTracker.stop() mapView?.get()?.onDestroy()
mapView?.clear()
super.onDestroy() super.onDestroy()
} }
private fun onMapReady() {
if (!isAdded) return
locationPinProvider.create(session.myUserId) {
views.mapView.addPinToMap(
pinId = USER_PIN_NAME,
image = it,
)
// All set, start location tracker
locationTracker.start()
}
}
override fun onLocationUpdate(locationData: LocationData) {
lastZoomValue = if (lastZoomValue == -1.0) INITIAL_MAP_ZOOM else views.mapView.getCurrentZoom() ?: INITIAL_MAP_ZOOM
views.mapView.zoomToLocation(locationData.latitude, locationData.longitude, lastZoomValue)
views.mapView.deleteAllPins()
views.mapView.updatePinLocation(USER_PIN_NAME, locationData.latitude, locationData.longitude)
viewModel.handle(LocationSharingAction.OnLocationUpdate(locationData))
}
override fun onLocationProviderIsNotAvailable() {
viewModel.handle(LocationSharingAction.OnLocationProviderIsNotAvailable)
}
private fun handleLocationNotAvailableError() { private fun handleLocationNotAvailableError() {
MaterialAlertDialogBuilder(requireActivity()) MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.location_not_available_dialog_title) .setTitle(R.string.location_not_available_dialog_title)
@ -118,9 +110,15 @@ class LocationSharingFragment @Inject constructor(
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
activity?.finish() activity?.finish()
} }
.setCancelable(false)
.show() .show()
} }
override fun invalidate() = withState(viewModel) { state ->
views.mapView.render(state.toMapState())
views.shareLocationGpsLoading.isGone = state.lastKnownLocation != null
}
companion object { companion object {
const val USER_PIN_NAME = "USER_PIN_NAME" const val USER_PIN_NAME = "USER_PIN_NAME"
} }

View file

@ -24,12 +24,15 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
class LocationSharingViewModel @AssistedInject constructor( class LocationSharingViewModel @AssistedInject constructor(
@Assisted private val initialState: LocationSharingViewState, @Assisted private val initialState: LocationSharingViewState,
session: Session private val locationTracker: LocationTracker,
) : VectorViewModel<LocationSharingViewState, LocationSharingAction, LocationSharingViewEvents>(initialState) { private val locationPinProvider: LocationPinProvider,
private val session: Session
) : VectorViewModel<LocationSharingViewState, LocationSharingAction, LocationSharingViewEvents>(initialState), LocationTracker.Callback {
private val room = session.getRoom(initialState.roomId)!! private val room = session.getRoom(initialState.roomId)!!
@ -38,14 +41,31 @@ class LocationSharingViewModel @AssistedInject constructor(
override fun create(initialState: LocationSharingViewState): LocationSharingViewModel override fun create(initialState: LocationSharingViewState): LocationSharingViewModel
} }
companion object : MavericksViewModelFactory<LocationSharingViewModel, LocationSharingViewState> by hiltMavericksViewModelFactory() { companion object : MavericksViewModelFactory<LocationSharingViewModel, LocationSharingViewState> by hiltMavericksViewModelFactory()
init {
locationTracker.start(this)
createPin()
}
private fun createPin() {
locationPinProvider.create(session.myUserId) {
setState {
copy(
pinDrawable = it
)
}
}
}
override fun onCleared() {
super.onCleared()
locationTracker.stop()
} }
override fun handle(action: LocationSharingAction) { override fun handle(action: LocationSharingAction) {
when (action) { when (action) {
is LocationSharingAction.OnLocationUpdate -> handleLocationUpdate(action.locationData)
LocationSharingAction.OnShareLocation -> handleShareLocation() LocationSharingAction.OnShareLocation -> handleShareLocation()
LocationSharingAction.OnLocationProviderIsNotAvailable -> handleLocationProviderIsNotAvailable()
}.exhaustive }.exhaustive
} }
@ -62,13 +82,13 @@ class LocationSharingViewModel @AssistedInject constructor(
} }
} }
private fun handleLocationUpdate(locationData: LocationData) { override fun onLocationUpdate(locationData: LocationData) {
setState { setState {
copy(lastKnownLocation = locationData) copy(lastKnownLocation = locationData)
} }
} }
private fun handleLocationProviderIsNotAvailable() { override fun onLocationProviderIsNotAvailable() {
_viewEvents.post(LocationSharingViewEvents.LocationNotAvailableError) _viewEvents.post(LocationSharingViewEvents.LocationNotAvailableError)
} }
} }

View file

@ -16,6 +16,7 @@
package im.vector.app.features.location package im.vector.app.features.location
import android.graphics.drawable.Drawable
import androidx.annotation.StringRes import androidx.annotation.StringRes
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
import im.vector.app.R import im.vector.app.R
@ -28,7 +29,8 @@ enum class LocationSharingMode(@StringRes val titleRes: Int) {
data class LocationSharingViewState( data class LocationSharingViewState(
val roomId: String, val roomId: String,
val mode: LocationSharingMode, val mode: LocationSharingMode,
val lastKnownLocation: LocationData? = null val lastKnownLocation: LocationData? = null,
val pinDrawable: Drawable? = null
) : MavericksState { ) : MavericksState {
constructor(locationSharingArgs: LocationSharingArgs) : this( constructor(locationSharingArgs: LocationSharingArgs) : this(
@ -36,3 +38,10 @@ data class LocationSharingViewState(
mode = locationSharingArgs.mode mode = locationSharingArgs.mode
) )
} }
fun LocationSharingViewState.toMapState() = MapState(
zoomOnlyOnce = true,
pinLocationData = lastKnownLocation,
pinId = LocationSharingFragment.USER_PIN_NAME,
pinDrawable = pinDrawable
)

View file

@ -19,70 +19,108 @@ package im.vector.app.features.location
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
import android.location.Location import android.location.Location
import android.location.LocationListener
import android.location.LocationManager import android.location.LocationManager
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.location.LocationListenerCompat
import im.vector.app.BuildConfig
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class LocationTracker @Inject constructor( class LocationTracker @Inject constructor(
private val context: Context context: Context
) : LocationListener { ) : LocationListenerCompat {
private val locationManager = context.getSystemService<LocationManager>()
interface Callback { interface Callback {
fun onLocationUpdate(locationData: LocationData) fun onLocationUpdate(locationData: LocationData)
fun onLocationProviderIsNotAvailable() fun onLocationProviderIsNotAvailable()
} }
private var locationManager: LocationManager? = null private var callback: Callback? = null
var callback: Callback? = null
private var hasGpsProviderLiveLocation = false
@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION]) @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
fun start() { fun start(callback: Callback?) {
val locationManager = context.getSystemService<LocationManager>() Timber.d("## LocationTracker. start()")
hasGpsProviderLiveLocation = false
this.callback = callback
locationManager?.let { if (locationManager == null) {
val isGpsEnabled = it.isProviderEnabled(LocationManager.GPS_PROVIDER)
val isNetworkEnabled = it.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
val provider = when {
isGpsEnabled -> LocationManager.GPS_PROVIDER
isNetworkEnabled -> LocationManager.NETWORK_PROVIDER
else -> {
callback?.onLocationProviderIsNotAvailable()
Timber.v("## LocationTracker. There is no location provider available")
return
}
}
// Send last known location without waiting location updates
it.getLastKnownLocation(provider)?.let { lastKnownLocation ->
callback?.onLocationUpdate(lastKnownLocation.toLocationData())
}
it.requestLocationUpdates(
provider,
MIN_TIME_MILLIS_TO_UPDATE_LOCATION,
MIN_DISTANCE_METERS_TO_UPDATE_LOCATION,
this
)
} ?: run {
callback?.onLocationProviderIsNotAvailable() callback?.onLocationProviderIsNotAvailable()
Timber.v("## LocationTracker. LocationManager is not available") Timber.v("## LocationTracker. LocationManager is not available")
return
}
locationManager.allProviders
.takeIf { it.isNotEmpty() }
// Take GPS first
?.sortedByDescending { if (it == LocationManager.GPS_PROVIDER) 1 else 0 }
?.forEach { provider ->
Timber.d("## LocationTracker. track location using $provider")
// Send last known location without waiting location updates
locationManager.getLastKnownLocation(provider)?.let { lastKnownLocation ->
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
Timber.d("## LocationTracker. lastKnownLocation: $lastKnownLocation")
} else {
Timber.d("## LocationTracker. lastKnownLocation: ${lastKnownLocation.provider}")
}
notifyLocation(lastKnownLocation, isLive = false)
}
locationManager.requestLocationUpdates(
provider,
MIN_TIME_TO_UPDATE_LOCATION_MILLIS,
MIN_DISTANCE_TO_UPDATE_LOCATION_METERS,
this
)
}
?: run {
callback?.onLocationProviderIsNotAvailable()
Timber.v("## LocationTracker. There is no location provider available")
} }
} }
@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION]) @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
fun stop() { fun stop() {
Timber.d("## LocationTracker. stop()")
locationManager?.removeUpdates(this) locationManager?.removeUpdates(this)
callback = null callback = null
} }
override fun onLocationChanged(location: Location) { override fun onLocationChanged(location: Location) {
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
Timber.d("## LocationTracker. onLocationChanged: $location")
} else {
Timber.d("## LocationTracker. onLocationChanged: ${location.provider}")
}
notifyLocation(location, isLive = true)
}
private fun notifyLocation(location: Location, isLive: Boolean) {
when (location.provider) {
LocationManager.GPS_PROVIDER -> {
hasGpsProviderLiveLocation = isLive
}
else -> {
if (hasGpsProviderLiveLocation) {
// Ignore this update
Timber.d("## LocationTracker. ignoring location from ${location.provider}, we have gps live location")
return
}
}
}
callback?.onLocationUpdate(location.toLocationData()) callback?.onLocationUpdate(location.toLocationData())
} }
override fun onProviderDisabled(provider: String) {
Timber.d("## LocationTracker. onProviderDisabled: $provider")
callback?.onLocationProviderIsNotAvailable()
}
private fun Location.toLocationData(): LocationData { private fun Location.toLocationData(): LocationData {
return LocationData(latitude, longitude, accuracy.toDouble()) return LocationData(latitude, longitude, accuracy.toDouble())
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 New Vector Ltd * Copyright (c) 2022 New Vector Ltd
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,15 +18,9 @@ package im.vector.app.features.location
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
interface VectorMapView { data class MapState(
fun initialize(onMapReady: () -> Unit) val zoomOnlyOnce: Boolean,
val pinLocationData: LocationData? = null,
fun addPinToMap(pinId: String, image: Drawable) val pinId: String,
fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) val pinDrawable: Drawable? = null
fun deleteAllPins() )
fun zoomToLocation(latitude: Double, longitude: Double, zoom: Double)
fun getCurrentZoom(): Double?
fun onClick(callback: () -> Unit)
}

View file

@ -17,7 +17,6 @@
package im.vector.app.features.location package im.vector.app.features.location
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import com.mapbox.mapboxsdk.camera.CameraPosition import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng import com.mapbox.mapboxsdk.geometry.LatLng
@ -27,65 +26,76 @@ import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
import com.mapbox.mapboxsdk.style.layers.Property import com.mapbox.mapboxsdk.style.layers.Property
import im.vector.app.BuildConfig import timber.log.Timber
class MapTilerMapView @JvmOverloads constructor( class MapTilerMapView @JvmOverloads constructor(
context: Context, context: Context,
attrs: AttributeSet? = null, attrs: AttributeSet? = null,
defStyleAttr: Int = 0 defStyleAttr: Int = 0
) : MapView(context, attrs, defStyleAttr), VectorMapView { ) : MapView(context, attrs, defStyleAttr) {
private var map: MapboxMap? = null private var pendingState: MapState? = null
private var symbolManager: SymbolManager? = null
private var style: Style? = null
override fun initialize(onMapReady: () -> Unit) { data class MapRefs(
val map: MapboxMap,
val symbolManager: SymbolManager,
val style: Style
)
private var mapRefs: MapRefs? = null
private var initZoomDone = false
/**
* For location fragments
*/
fun initialize(url: String) {
Timber.d("## Location: initialize")
getMapAsync { map -> getMapAsync { map ->
map.setStyle(styleUrl) { style -> map.setStyle(url) { style ->
this.symbolManager = SymbolManager(this, map, style) mapRefs = MapRefs(
this.map = map map,
this.style = style SymbolManager(this, map, style),
onMapReady() style
)
pendingState?.let { render(it) }
pendingState = null
} }
} }
} }
override fun addPinToMap(pinId: String, image: Drawable) { fun render(state: MapState) {
style?.addImage(pinId, image) val safeMapRefs = mapRefs ?: return Unit.also {
pendingState = state
} }
override fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) { state.pinDrawable?.let { pinDrawable ->
symbolManager?.create( if (!safeMapRefs.style.isFullyLoaded ||
safeMapRefs.style.getImage(state.pinId) == null) {
safeMapRefs.style.addImage(state.pinId, pinDrawable)
}
}
state.pinLocationData?.let { locationData ->
if (!initZoomDone || !state.zoomOnlyOnce) {
zoomToLocation(locationData.latitude, locationData.longitude)
initZoomDone = true
}
safeMapRefs.symbolManager.deleteAll()
safeMapRefs.symbolManager.create(
SymbolOptions() SymbolOptions()
.withLatLng(LatLng(latitude, longitude)) .withLatLng(LatLng(locationData.latitude, locationData.longitude))
.withIconImage(pinId) .withIconImage(state.pinId)
.withIconAnchor(Property.ICON_ANCHOR_BOTTOM) .withIconAnchor(Property.ICON_ANCHOR_BOTTOM)
) )
} }
override fun deleteAllPins() {
symbolManager?.deleteAll()
} }
override fun zoomToLocation(latitude: Double, longitude: Double, zoom: Double) { private fun zoomToLocation(latitude: Double, longitude: Double) {
map?.cameraPosition = CameraPosition.Builder() Timber.d("## Location: zoomToLocation")
mapRefs?.map?.cameraPosition = CameraPosition.Builder()
.target(LatLng(latitude, longitude)) .target(LatLng(latitude, longitude))
.zoom(zoom) .zoom(INITIAL_MAP_ZOOM_IN_PREVIEW)
.build() .build()
} }
override fun getCurrentZoom(): Double? {
return map?.cameraPosition?.zoom
}
override fun onClick(callback: () -> Unit) {
map?.addOnMapClickListener {
callback()
true
}
}
companion object {
private const val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=${BuildConfig.mapTilerKey}"
}
} }

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.location
import android.content.res.Resources
import im.vector.app.BuildConfig
import im.vector.app.R
import javax.inject.Inject
class UrlMapProvider @Inject constructor(
private val resources: Resources
) {
private val keyParam = "?key=${BuildConfig.mapTilerKey}"
// This is static so no need for a fun
val mapUrl = buildString {
append(MAP_BASE_URL)
append(keyParam)
}
fun buildStaticMapUrl(locationData: LocationData,
zoom: Double,
width: Int,
height: Int): String {
return buildString {
append(STATIC_MAP_BASE_URL)
append(locationData.longitude)
append(",")
append(locationData.latitude)
append(",")
append(zoom)
append("/")
append(width)
append("x")
append(height)
append(".png")
append(keyParam)
if (!resources.getBoolean(R.bool.is_rtl)) {
// On LTR languages we want the legal mentions to be displayed on the bottom left of the image
append("&attribution=bottomleft")
}
}
}
}

View file

@ -535,9 +535,13 @@ class DefaultNavigator @Inject constructor(
context.startActivity(RoomDevToolActivity.intent(context, roomId)) context.startActivity(RoomDevToolActivity.intent(context, roomId))
} }
override fun openCallTransfer(context: Context, callId: String) { override fun openCallTransfer(
context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
callId: String
) {
val intent = CallTransferActivity.newIntent(context, callId) val intent = CallTransferActivity.newIntent(context, callId)
context.startActivity(intent) activityResultLauncher.launch(intent)
} }
override fun openCreatePoll(context: Context, roomId: String, editedEventId: String?, mode: PollMode) { override fun openCreatePoll(context: Context, roomId: String, editedEventId: String?, mode: PollMode) {

View file

@ -150,7 +150,11 @@ interface Navigator {
fun openDevTools(context: Context, roomId: String) fun openDevTools(context: Context, roomId: String)
fun openCallTransfer(context: Context, callId: String) fun openCallTransfer(
context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
callId: String
)
fun openCreatePoll(context: Context, roomId: String, editedEventId: String?, mode: PollMode) fun openCreatePoll(context: Context, roomId: String, editedEventId: String?, mode: PollMode)

View file

@ -20,6 +20,7 @@ import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.notifications.ProcessedEvent.Type.KEEP import im.vector.app.features.notifications.ProcessedEvent.Type.KEEP
import im.vector.app.features.notifications.ProcessedEvent.Type.REMOVE import im.vector.app.features.notifications.ProcessedEvent.Type.REMOVE
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
private typealias ProcessedEvents = List<ProcessedEvent<NotifiableEvent>> private typealias ProcessedEvents = List<ProcessedEvent<NotifiableEvent>>
@ -33,9 +34,13 @@ class NotifiableEventProcessor @Inject constructor(
val processedEvents = queuedEvents.map { val processedEvents = queuedEvents.map {
val type = when (it) { val type = when (it) {
is InviteNotifiableEvent -> if (autoAcceptInvites.hideInvites) REMOVE else KEEP is InviteNotifiableEvent -> if (autoAcceptInvites.hideInvites) REMOVE else KEEP
is NotifiableMessageEvent -> if (shouldIgnoreMessageEventInRoom(currentRoomId, it.roomId) || outdatedDetector.isMessageOutdated(it)) { is NotifiableMessageEvent -> when {
REMOVE shouldIgnoreMessageEventInRoom(currentRoomId, it.roomId) -> REMOVE
} else KEEP .also { Timber.d("notification message removed due to currently viewing the same room") }
outdatedDetector.isMessageOutdated(it) -> REMOVE
.also { Timber.d("notification message removed due to being read") }
else -> KEEP
}
is SimpleNotifiableEvent -> when (it.type) { is SimpleNotifiableEvent -> when (it.type) {
EventType.REDACTION -> REMOVE EventType.REDACTION -> REMOVE
else -> KEEP else -> KEEP

View file

@ -55,12 +55,12 @@ class PushRuleTriggerListener @Inject constructor(
private suspend fun createNotifiableEvents(pushEvents: PushEvents, session: Session): List<NotifiableEvent> { private suspend fun createNotifiableEvents(pushEvents: PushEvents, session: Session): List<NotifiableEvent> {
return pushEvents.matchedEvents.mapNotNull { (event, pushRule) -> return pushEvents.matchedEvents.mapNotNull { (event, pushRule) ->
Timber.v("Push rule match for event ${event.eventId}") Timber.d("Push rule match for event ${event.eventId}")
val action = pushRule.getActions().toNotificationAction() val action = pushRule.getActions().toNotificationAction()
if (action.shouldNotify) { if (action.shouldNotify) {
resolver.resolveEvent(event, session, isNoisy = !action.soundName.isNullOrBlank()) resolver.resolveEvent(event, session, isNoisy = !action.soundName.isNullOrBlank())
} else { } else {
Timber.v("Matched push rule is set to not notify") Timber.d("Matched push rule is set to not notify")
null null
} }
} }

View file

@ -48,4 +48,13 @@
android:textColor="?colorPrimary" android:textColor="?colorPrimary"
android:textStyle="bold" /> android:textStyle="bold" />
<ProgressBar
android:id="@+id/shareLocationGpsLoading"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="@dimen/layout_horizontal_margin"
app:layout_constraintBottom_toBottomOf="@id/shareLocationContainer"
app:layout_constraintEnd_toEndOf="@id/shareLocationContainer"
app:layout_constraintTop_toTopOf="@id/shareLocationContainer" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -103,18 +103,34 @@
tools:text="1080 x 1024 - 43s - 12kB" tools:text="1080 x 1024 - 43s - 12kB"
tools:visibility="visible" /> tools:visibility="visible" />
<im.vector.app.features.location.MapTilerMapView
android:id="@+id/bottom_sheet_message_preview_location" <com.google.android.material.card.MaterialCardView
android:id="@+id/mapViewContainer"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="200dp" android:layout_height="wrap_content"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:contentDescription="@string/attachment_type_location"
android:scaleType="centerCrop"
android:visibility="gone" android:visibility="gone"
app:cardCornerRadius="8dp"
app:layout_constraintEnd_toEndOf="@id/bottom_sheet_message_preview_timestamp" app:layout_constraintEnd_toEndOf="@id/bottom_sheet_message_preview_timestamp"
app:layout_constraintStart_toStartOf="@id/bottom_sheet_message_preview_sender" app:layout_constraintStart_toStartOf="@id/bottom_sheet_message_preview_sender"
app:layout_constraintTop_toBottomOf="@id/bottom_sheet_message_preview_sender" app:layout_constraintTop_toBottomOf="@id/bottom_sheet_message_preview_sender"
app:mapbox_renderTextureMode="true" tools:alpha="0.3"
tools:visibility="visible" /> tools:visibility="visible">
<ImageView
android:id="@+id/staticMapImageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:contentDescription="@string/a11y_static_map_image" />
<ImageView
android:id="@+id/staticMapPinImageView"
android:layout_width="51dp"
android:layout_height="55dp"
android:layout_gravity="center"
android:layout_marginBottom="28dp"
android:importantForAccessibility="no"
android:src="@drawable/bg_map_user_pin" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -6,30 +6,19 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardCornerRadius="8dp"> app:cardCornerRadius="8dp">
<androidx.constraintlayout.widget.ConstraintLayout <ImageView
android:id="@+id/mapViewContainer" android:id="@+id/staticMapImageView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content">
<im.vector.app.features.location.MapTilerMapView
android:id="@+id/mapView"
android:layout_width="0dp"
android:layout_height="200dp" android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent" android:contentDescription="@string/a11y_static_map_image" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mapbox_renderTextureMode="true" />
<FrameLayout <ImageView
android:id="@+id/clickableMapArea" android:id="@+id/staticMapPinImageView"
android:layout_width="0dp" android:layout_width="51dp"
android:layout_height="0dp" android:layout_height="55dp"
app:layout_constraintBottom_toBottomOf="@id/mapView" android:layout_gravity="center"
app:layout_constraintEnd_toEndOf="@id/mapView" android:layout_marginBottom="28dp"
app:layout_constraintStart_toStartOf="@id/mapView" android:importantForAccessibility="no"
app:layout_constraintTop_toTopOf="@id/mapView" /> android:src="@drawable/bg_map_user_pin" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>

View file

@ -611,7 +611,7 @@
<string name="room_participants_action_mention">Zmínit</string> <string name="room_participants_action_mention">Zmínit</string>
<string name="room_participants_action_devices_list">Zobrazit seznam relací</string> <string name="room_participants_action_devices_list">Zobrazit seznam relací</string>
<string name="room_preview_room_interactions_disabled">Toto je náhled místnosti. Interakce s místností byla vypnuta.</string> <string name="room_preview_room_interactions_disabled">Toto je náhled místnosti. Interakce s místností byla vypnuta.</string>
<string name="room_participants_ban_prompt_msg">Vykázání uživatele jej vykopne z této místnosti a zamezí, aby opět vstoupili.</string> <string name="room_participants_ban_prompt_msg">Vykázání uživatele jej odebere z této místnosti a zamezí, aby opět vstoupil.</string>
<string name="reason_hint">Důvod</string> <string name="reason_hint">Důvod</string>
<string name="room_participants_invite_prompt_msg">Opravdu chcete pozvat uživatele %s do této konverzace\?</string> <string name="room_participants_invite_prompt_msg">Opravdu chcete pozvat uživatele %s do této konverzace\?</string>
<string name="room_participants_invite_join_names">"%1$s, "</string> <string name="room_participants_invite_join_names">"%1$s, "</string>
@ -930,7 +930,7 @@
<string name="settings_show_read_receipts">Ukázat potvrzení o přečtení</string> <string name="settings_show_read_receipts">Ukázat potvrzení o přečtení</string>
<string name="settings_show_read_receipts_summary">Klepněte na potvrzení o přečtení pro podrobnosti.</string> <string name="settings_show_read_receipts_summary">Klepněte na potvrzení o přečtení pro podrobnosti.</string>
<string name="settings_show_join_leave_messages">Ukázat události příchodů a odchodů</string> <string name="settings_show_join_leave_messages">Ukázat události příchodů a odchodů</string>
<string name="settings_show_join_leave_messages_summary">Nemá vliv na pozvánky, nakopnutí a zákazy.</string> <string name="settings_show_join_leave_messages_summary">Pozvánky, odebrání a vykázání nejsou dotčeny.</string>
<string name="settings_show_avatar_display_name_changes_messages">Ukázat události účtu</string> <string name="settings_show_avatar_display_name_changes_messages">Ukázat události účtu</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">Zahrnout avatar a změny veřejného jména.</string> <string name="settings_show_avatar_display_name_changes_messages_summary">Zahrnout avatar a změny veřejného jména.</string>
<string name="settings_vibrate_on_mention">Vibrovat při zmínce uživatele</string> <string name="settings_vibrate_on_mention">Vibrovat při zmínce uživatele</string>
@ -2386,7 +2386,7 @@
<item quantity="other">%d vteřin</item> <item quantity="other">%d vteřin</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events">Zobrazit stavové události účastníků v místnosti</string> <string name="settings_show_room_member_state_events">Zobrazit stavové události účastníků v místnosti</string>
<string name="settings_show_room_member_state_events_summary">Zahrnuje události pozvat/vstoupit/opustit/vykopnout/vykázat a změny avatara/veřejného jména.</string> <string name="settings_show_room_member_state_events_summary">Zahrnuje události pozvat/vstoupit/opustit/odebrat/vykázat a změny avatara/veřejného jména.</string>
<string name="sent_a_poll">Hlasování</string> <string name="sent_a_poll">Hlasování</string>
<string name="sent_a_reaction">Reagoval(a): %s</string> <string name="sent_a_reaction">Reagoval(a): %s</string>
<string name="sent_verification_conclusion">Výsledek ověření</string> <string name="sent_verification_conclusion">Výsledek ověření</string>
@ -3010,7 +3010,7 @@
<string name="space_settings_permissions_subtitle">Zobrazit a aktualizovat role potřebné ke změně různých částí prostoru.</string> <string name="space_settings_permissions_subtitle">Zobrazit a aktualizovat role potřebné ke změně různých částí prostoru.</string>
<string name="space_settings_permissions_title">Oprávnění prostoru</string> <string name="space_settings_permissions_title">Oprávnění prostoru</string>
<string name="space_participants_unban_prompt_msg">Zrušením vykázání uživateli umožní znovu se připojit do prostoru.</string> <string name="space_participants_unban_prompt_msg">Zrušením vykázání uživateli umožní znovu se připojit do prostoru.</string>
<string name="space_participants_ban_prompt_msg">Vykázáním uživatele z tohoto prostoru vykopnete a zabráníte mu v dalším připojení.</string> <string name="space_participants_ban_prompt_msg">Vykázání uživatele z tohoto prostoru ho odebere a zamezí, aby opět vstoupil.</string>
<string name="space_participants_remove_prompt_msg">vykopnutí uživatele je z tohoto prostoru odstraní. <string name="space_participants_remove_prompt_msg">vykopnutí uživatele je z tohoto prostoru odstraní.
\n \n
\nAbyste jim zabránili v dalším vstupu, měli byste je raději vykázat.</string> \nAbyste jim zabránili v dalším vstupu, měli byste je raději vykázat.</string>
@ -3072,8 +3072,8 @@
<item quantity="other">Konečný výsledek na základě %1$d hlasů</item> <item quantity="other">Konečný výsledek na základě %1$d hlasů</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_not_voted"> <plurals name="poll_total_vote_count_before_ended_and_not_voted">
<item quantity="one">Nikdo nehlasoval</item> <item quantity="one">%1$d hlas. Hlasujte pro zobrazení výsledků</item>
<item quantity="few">%1$d hlasů. Hlasujte pro zobrazení výsledků</item> <item quantity="few">%1$d hlasy. Hlasujte pro zobrazení výsledků</item>
<item quantity="other">%1$d hlasů. Hlasujte pro zobrazení výsledků</item> <item quantity="other">%1$d hlasů. Hlasujte pro zobrazení výsledků</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_voted"> <plurals name="poll_total_vote_count_before_ended_and_voted">
@ -3120,7 +3120,40 @@
<string name="room_member_override_nick_color">Přepsat barvu přezdívky</string> <string name="room_member_override_nick_color">Přepsat barvu přezdívky</string>
<string name="login_splash_already_have_account">Již mám účet</string> <string name="login_splash_already_have_account">Již mám účet</string>
<string name="ftue_auth_carousel_4_title">Zlepšete týmovou komunikaci.</string> <string name="ftue_auth_carousel_4_title">Zlepšete týmovou komunikaci.</string>
<string name="ftue_auth_carousel_3_title">Spojte se s kýmkoli.</string> <string name="ftue_auth_carousel_3_title">Bezpečené zasílání zpráv.</string>
<string name="ftue_auth_carousel_2_title">Máte vše pod kontrolou.</string> <string name="ftue_auth_carousel_2_title">Máte vše pod kontrolou.</string>
<string name="ftue_auth_carousel_1_title">Vlastněte své konverzace.</string> <string name="ftue_auth_carousel_1_title">Vlastněte své konverzace.</string>
<string name="tooltip_attachment_location">Sdílet polohu</string>
<string name="labs_render_locations_in_timeline">Zobrazit polohy uživatele na časové ose</string>
<string name="settings_enable_location_sharing_summary">Po zapnutí budete moci odeslat svou polohu do libovolné místnosti</string>
<string name="settings_enable_location_sharing">Povolit sdílení polohy</string>
<string name="location_share_external">Otevřít v</string>
<string name="template_location_not_available_dialog_content">${app_name} nemohl získat přístup k vaší poloze. Zkuste to prosím později.</string>
<string name="template_location_not_available_dialog_title">${app_name} nemohl získat přístup k vaší poloze</string>
<string name="location_share">Sdílet polohu</string>
<string name="a11y_location_share_icon">Sdílet polohu</string>
<string name="location_activity_title_preview">Poloha</string>
<string name="location_activity_title_static_sharing">Sdílet polohu</string>
<string name="closed_poll_option_description">Výsledky se zobrazí až po ukončení hlasování</string>
<string name="closed_poll_option_title">Uzavřené hlasování</string>
<string name="open_poll_option_description">Hlasující vidí výsledky ihned po hlasování</string>
<string name="open_poll_option_title">Otevřené hlasování</string>
<string name="poll_type_title">Typ hlasování</string>
<string name="edit_poll_button">UPRAVIT HLASOVÁNÍ</string>
<string name="edit_poll_title">Upravit hlasování</string>
<string name="poll_no_votes_cast">Nikdo nehlasoval</string>
<string name="a11y_trust_level_misconfigured">Chybně nakonfigurovaná úroveň důvěryhodnosti</string>
<string name="encryption_misconfigured">Šifrování je špatně nakonfigurováno</string>
<string name="room_profile_section_restore_security">Obnovit šifrování</string>
<string name="room_unsupported_e2e_algorithm">Šifrování bylo špatně nakonfigurováno, takže nelze odesílat zprávy. Kontaktujte správce, aby obnovil šifrování do funkčního stavu.</string>
<string name="contact_admin_to_restore_encryption">Kontaktujte správce, aby obnovil šifrování do funkčního stavu.</string>
<string name="encryption_has_been_misconfigured">Šifrování bylo špatně nakonfigurováno.</string>
<string name="sent_location">Sdíleli svou polohu</string>
<string name="login_splash_create_account">Vytvořit účet</string>
<string name="ftue_auth_carousel_title_messaging">Zasílání zpráv pro váš tým.</string>
<string name="ftue_auth_carousel_body_encrypted">Koncové šifrování bez potřeby telefonního čísla. Žádné reklamy ani vytěžování dat.</string>
<string name="ftue_auth_carousel_body_control">Můžete si vybrat, kde budou vaše konverzace uloženy, a získat tak kontrolu a nezávislost. Připojeno přes Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Bezpečná a nezávislá komunikace, která vám poskytne stejnou úroveň soukromí jako osobní rozhovor u vás doma.</string>
<string name="attachment_type_location">Poloha</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Šifrování bylo špatně nakonfigurováno, takže nelze odesílat zprávy. Kliknutím otevřete nastavení.</string>
</resources> </resources>

View file

@ -3058,4 +3058,37 @@
<item quantity="other">Endgültiges Ergebnis basiert auf %1$d Stimmen</item> <item quantity="other">Endgültiges Ergebnis basiert auf %1$d Stimmen</item>
</plurals> </plurals>
<string name="ftue_auth_carousel_4_title">Element verbindet Datenschutz mit tollen Features.</string> <string name="ftue_auth_carousel_4_title">Element verbindet Datenschutz mit tollen Features.</string>
<string name="room_profile_section_restore_security">Verschlüsselung wiederherstellen</string>
<string name="tooltip_attachment_location">Standort freigeben</string>
<string name="location_share">Standort freigeben</string>
<string name="a11y_location_share_icon">Standort freigeben</string>
<string name="location_activity_title_static_sharing">Standort freigeben</string>
<string name="settings_enable_location_sharing">Standortfreigabe aktivieren</string>
<string name="location_share_external">Öffnen mit</string>
<string name="template_location_not_available_dialog_content">${app_name} konnte nicht auf deinen Standort zugreifen. Bitte versuche es später noch einmal.</string>
<string name="template_location_not_available_dialog_title">${app_name} konnte nicht auf deinen Standort zugreifen</string>
<string name="location_activity_title_preview">Standort</string>
<string name="closed_poll_option_description">Ergebnisse werden erst angezeigt, wenn du die Umfrage beendest</string>
<string name="closed_poll_option_title">Geschlossene Umfrage</string>
<string name="open_poll_option_description">Ergebnisse werden direkt nach Stimmabgabe angezeigt</string>
<string name="open_poll_option_title">Offene Umfrage</string>
<string name="poll_type_title">Umfragetyp</string>
<string name="edit_poll_button">UMFRAGE BEARBEITEN</string>
<string name="edit_poll_title">Umfrage bearbeiten</string>
<string name="poll_no_votes_cast">Keine Stimmen abgegeben</string>
<string name="login_splash_create_account">Konto erstellen</string>
<string name="ftue_auth_carousel_title_messaging">Nachrichtenaustausch für dein Team.</string>
<string name="ftue_auth_carousel_body_encrypted">Ende-zu-Ende-verschlüsselt und ohne Telefonnummer nutzbar. Keine Werbung oder Datenerfassung.</string>
<string name="ftue_auth_carousel_body_control">Wähle wo deine Gespräche liegen, für Kontrolle und Unabhängigkeit. Verbunden mit Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Sichere und unabhängige Kommunikation, die für die gleiche Vertraulichkeit sorgt, wie ein Gespräch von Angesicht zu Angesicht in deinem eigenen Zuhause.</string>
<string name="attachment_type_location">Standort</string>
<string name="a11y_trust_level_misconfigured">Fehlerhaft konfiguriertes Vertrauenslevel</string>
<string name="encryption_misconfigured">Die Verschlüsselung ist fehlerhaft konfiguriert</string>
<string name="contact_admin_to_restore_encryption">Bitte kontaktiere einen Admin, um die Verschlüsselung zurückzusetzen.</string>
<string name="encryption_has_been_misconfigured">Die Verschlüsselung wurde fehlerhaft konfiguriert.</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Die Verschlüsselung wurde fehlerhaft konfiguriert und du kannst keine Nachrichten senden. Klicke, um die Einstellungen zu öffnen.</string>
<string name="room_unsupported_e2e_algorithm">Die Verschlüsselung wurde fehlerhaft konfiguriert und du kannst keine Nachrichten senden. Bitte kontaktiere einen Admin, um die Verschlüsselung wiederherzustellen.</string>
<string name="labs_render_locations_in_timeline">Geteilte Standorte anzeigen</string>
<string name="settings_enable_location_sharing_summary">Sobald aktiviert, kannst du deinen Standort in jeden Raum senden</string>
<string name="sent_location">Hat den Standort geteilt</string>
</resources> </resources>

View file

@ -1381,7 +1381,7 @@
<string name="settings_always_show_timestamps">Näita kõikide sõnumite ajatempleid</string> <string name="settings_always_show_timestamps">Näita kõikide sõnumite ajatempleid</string>
<string name="settings_show_read_receipts_summary">Lugemisteatisele klõpsimine kuvab detailsema loendi.</string> <string name="settings_show_read_receipts_summary">Lugemisteatisele klõpsimine kuvab detailsema loendi.</string>
<string name="settings_show_join_leave_messages">Näita jututubadega liitumised ja neist lahkumised</string> <string name="settings_show_join_leave_messages">Näita jututubadega liitumised ja neist lahkumised</string>
<string name="settings_show_join_leave_messages_summary">Siia alla ei kuulu kutsed, müksamised ja suhtluskeelud.</string> <string name="settings_show_join_leave_messages_summary">Siia alla ei kuulu kutsed, eemaldamised ja suhtluskeelud.</string>
<string name="settings_show_avatar_display_name_changes_messages">Näita kontoga seotud sündmusi</string> <string name="settings_show_avatar_display_name_changes_messages">Näita kontoga seotud sündmusi</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">Sealhulgas tunnuspildi ja kuvatava nime muutusi.</string> <string name="settings_show_avatar_display_name_changes_messages_summary">Sealhulgas tunnuspildi ja kuvatava nime muutusi.</string>
<string name="settings_vibrate_on_mention">Kasutaja mainimisel anna väringa märku</string> <string name="settings_vibrate_on_mention">Kasutaja mainimisel anna väringa märku</string>
@ -2342,7 +2342,7 @@
<item quantity="other">%d sekundit</item> <item quantity="other">%d sekundit</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events">Näita jututoa liikmete olekusündmusi</string> <string name="settings_show_room_member_state_events">Näita jututoa liikmete olekusündmusi</string>
<string name="settings_show_room_member_state_events_summary">Sealhulgas kutsumisi, liitumisi, lahkumisi, müksamisi, keelamisi ning tunnuspildi ja kuvatava nime muutusi.</string> <string name="settings_show_room_member_state_events_summary">Sealhulgas kutsumisi, liitumisi, lahkumisi, eemaldamisi, keelamisi ning tunnuspildi ja kuvatava nime muutusi.</string>
<string name="sent_a_poll">Küsitlus</string> <string name="sent_a_poll">Küsitlus</string>
<string name="sent_a_reaction">Reageeris: %s</string> <string name="sent_a_reaction">Reageeris: %s</string>
<string name="sent_verification_conclusion">Verifitseerimise tulemus</string> <string name="sent_verification_conclusion">Verifitseerimise tulemus</string>
@ -3061,7 +3061,40 @@
<string name="room_member_override_nick_color">Asenda hüüdnime värvid</string> <string name="room_member_override_nick_color">Asenda hüüdnime värvid</string>
<string name="login_splash_already_have_account">Mul on kasutajakonto juba olemas</string> <string name="login_splash_already_have_account">Mul on kasutajakonto juba olemas</string>
<string name="ftue_auth_carousel_4_title">Lase tiimidel vabalt tegutseda.</string> <string name="ftue_auth_carousel_4_title">Lase tiimidel vabalt tegutseda.</string>
<string name="ftue_auth_carousel_3_title">Suhtle kellega soovid.</string> <string name="ftue_auth_carousel_3_title">Turvaline sõnumivahetus.</string>
<string name="ftue_auth_carousel_2_title">Sul on kontroll oma andmete üle.</string> <string name="ftue_auth_carousel_2_title">Sul on kontroll oma andmete üle.</string>
<string name="ftue_auth_carousel_1_title">Vestlused, mida sa tegelikult ka omad.</string> <string name="ftue_auth_carousel_1_title">Vestlused, mida sa tegelikult ka omad.</string>
<string name="tooltip_attachment_location">Jaga asukohta</string>
<string name="labs_render_locations_in_timeline">Kuva ajajoonel kasutaja asukohti</string>
<string name="settings_enable_location_sharing_summary">Kui see seadistus on kasutusel, siis sa saad oma asukohta jagada igas jututoas</string>
<string name="settings_enable_location_sharing">Luba asukohta jagada</string>
<string name="location_share_external">Ava muu rakendusega</string>
<string name="template_location_not_available_dialog_content">${app_name} ei saanud asukohta tuvastada. Palun proovi hiljem uuesti.</string>
<string name="template_location_not_available_dialog_title">${app_name} ei saanud asukohta tuvastada</string>
<string name="location_share">Jaga asukohta</string>
<string name="a11y_location_share_icon">Jaga asukohta</string>
<string name="location_activity_title_preview">Asukoht</string>
<string name="location_activity_title_static_sharing">Jaga asukohta</string>
<string name="closed_poll_option_description">Tulemusi kuvame vaid siis, kui küsitlus on lõppenud</string>
<string name="closed_poll_option_title">Küsitlus on lõppenud</string>
<string name="open_poll_option_description">Osalejad näevad tulemusi peale oma valiku salvestamist</string>
<string name="open_poll_option_title">Ava küsitlus</string>
<string name="poll_type_title">Küsitluse tüüp</string>
<string name="edit_poll_button">MUUDA KÜSITLUST</string>
<string name="edit_poll_title">Muuda küsitlust</string>
<string name="poll_no_votes_cast">Hääletanuid ei ole</string>
<string name="a11y_trust_level_misconfigured">Seadmete usaldusseosed on valesti seadistatud</string>
<string name="encryption_misconfigured">Krüptimise seadistustes on viga</string>
<string name="room_profile_section_restore_security">Taasta krüptimine</string>
<string name="contact_admin_to_restore_encryption">Kui soovid krüptimist töökorda saada, siis võta ühendust serveri haldajaga.</string>
<string name="encryption_has_been_misconfigured">Krüptimise seadistustes on viga.</string>
<string name="sent_location">Jagas oma asukohta</string>
<string name="login_splash_create_account">Loo kasutajakonto</string>
<string name="ftue_auth_carousel_title_messaging">Sõnumisuhtlus sinu tiimi või kogukonna jaoks.</string>
<string name="ftue_auth_carousel_body_encrypted">Tagatud on andmete läbiv krüptimine ning oma telefoninumbrit ei pea sa jagama. Pole reklaame ega sinu andmete kogumist.</string>
<string name="ftue_auth_carousel_body_control">Sa ise valid serveri, kus sinu vestlusi hoitakse ning sellega tagadki kontrolli oma andmete üle. Lahendus põhineb Matrix\'i võrgul.</string>
<string name="ftue_auth_carousel_body_secure">Turvaline ja sõltumatu suhtluslahendus, mis tagab sama privaatsuse, kui omavaheline vestlus sinu kodus.</string>
<string name="attachment_type_location">Asukoht</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Krüptimise seadistustes on viga ja sa ei saa sõnumeid saata. Seadistuste avamiseks klõpsi siin.</string>
<string name="room_unsupported_e2e_algorithm">Krüptimise seadistustes on viga ja sa ei saa sõnumeid saata. Kui soovid krüptimist töökorda saada, siis võta ühendust serveri haldajaga.</string>
</resources> </resources>

View file

@ -815,7 +815,7 @@
<string name="room_participants_action_unignore">لغو نادیده‌گیری</string> <string name="room_participants_action_unignore">لغو نادیده‌گیری</string>
<string name="room_participants_action_mention">اشاره</string> <string name="room_participants_action_mention">اشاره</string>
<string name="room_participants_action_devices_list">نمایش فهرست نشست</string> <string name="room_participants_action_devices_list">نمایش فهرست نشست</string>
<string name="room_participants_ban_prompt_msg">انسداد کاربر، او را از این اتاق اخراج کرده و از پیوستن دوباره‌اش جلوگیری می‌کند.</string> <string name="room_participants_ban_prompt_msg">انسداد کاربر، او را از این اتاق برداشته و از پیوستن دوباره‌اش جلوگیری می‌کند.</string>
<string name="reason_hint">دلیل</string> <string name="reason_hint">دلیل</string>
<string name="room_details_settings">تنظیمات</string> <string name="room_details_settings">تنظیمات</string>
<string name="tab_title_search_messages">پیام‌ها</string> <string name="tab_title_search_messages">پیام‌ها</string>
@ -1002,7 +1002,7 @@
\nمدیرهای یکپارچگی، داده‌های پیکربندی را دریافت کرده و می‌توانند از طرف شما ابزارک‌ها را تغییر داده، دعوت‌های اتاق فرستاده و سطوح قدرت را تنظیم کنند.</string> \nمدیرهای یکپارچگی، داده‌های پیکربندی را دریافت کرده و می‌توانند از طرف شما ابزارک‌ها را تغییر داده، دعوت‌های اتاق فرستاده و سطوح قدرت را تنظیم کنند.</string>
<string name="settings_always_show_timestamps">نمایش برچسب زمانی برای تمامی پیام‌ها</string> <string name="settings_always_show_timestamps">نمایش برچسب زمانی برای تمامی پیام‌ها</string>
<string name="settings_12_24_timestamps">نمایش برچسب‌های زمانی در قالب ۱۲ساعته</string> <string name="settings_12_24_timestamps">نمایش برچسب‌های زمانی در قالب ۱۲ساعته</string>
<string name="settings_show_room_member_state_events_summary">شامل رویدادهای دعوت/پیوستن/ترک/اخراج/تحریم و تغییرهای چهرک/نام نمایشی.</string> <string name="settings_show_room_member_state_events_summary">شامل رویدادهای دعوت/پیوستن/ترک/برداشتن/تحریم و تغییرهای چهرک/نام نمایشی.</string>
<string name="settings_secure_backup_section_title">پشتیبان امن</string> <string name="settings_secure_backup_section_title">پشتیبان امن</string>
<string name="settings_secure_backup_manage">مدیریت</string> <string name="settings_secure_backup_manage">مدیریت</string>
<string name="settings_secure_backup_setup">برپایی پشتیبان امن</string> <string name="settings_secure_backup_setup">برپایی پشتیبان امن</string>
@ -2956,7 +2956,7 @@
<string name="space_settings_permissions_subtitle">دیدن و به‌روز رسانی نقش‌های لازم برای تغییر بخش‌های مختلف فضا.</string> <string name="space_settings_permissions_subtitle">دیدن و به‌روز رسانی نقش‌های لازم برای تغییر بخش‌های مختلف فضا.</string>
<string name="space_settings_permissions_title">اجازه‌های فضا</string> <string name="space_settings_permissions_title">اجازه‌های فضا</string>
<string name="space_participants_unban_prompt_msg">لغو تحریم کاربر، اجازهٔ پیوستن دوباره‌اش به فضا را می‌دهد.</string> <string name="space_participants_unban_prompt_msg">لغو تحریم کاربر، اجازهٔ پیوستن دوباره‌اش به فضا را می‌دهد.</string>
<string name="space_participants_ban_prompt_msg">تحریم کاربر، او را از این فضا اخراج کرده و از پیوستن دوباره‌اش جلوگیری می‌کند.</string> <string name="space_participants_ban_prompt_msg">تحریم کاربر، او را از این فضا برداشته و از پیوستن دوباره‌اش جلوگیری می‌کند.</string>
<string name="space_participants_remove_prompt_msg">اخراج کاربر، از این فضا برش می‌دارد. <string name="space_participants_remove_prompt_msg">اخراج کاربر، از این فضا برش می‌دارد.
\n \n
\nبرای پیش‌گیری از پیوستن دوباره، باید تحریمش کنید.</string> \nبرای پیش‌گیری از پیوستن دوباره، باید تحریمش کنید.</string>
@ -3059,7 +3059,25 @@
<string name="labs_auto_report_uisi_desc">سامانه‌تان هنگام‌ مواجهه با خطای ناتوانی در رمزگشایی، گزارش‌ها را به صورت خودکار خواهد فرستاد</string> <string name="labs_auto_report_uisi_desc">سامانه‌تان هنگام‌ مواجهه با خطای ناتوانی در رمزگشایی، گزارش‌ها را به صورت خودکار خواهد فرستاد</string>
<string name="labs_auto_report_uisi">گزارش خودکار خطاهای رمزگشایی.</string> <string name="labs_auto_report_uisi">گزارش خودکار خطاهای رمزگشایی.</string>
<string name="login_splash_already_have_account">از پیش حساب دارم</string> <string name="login_splash_already_have_account">از پیش حساب دارم</string>
<string name="ftue_auth_carousel_3_title">ارتباط با هرکسی.</string> <string name="ftue_auth_carousel_3_title">پیام‌رسانی امن.</string>
<string name="ftue_auth_carousel_2_title">شما کنترل می‌کنید.</string> <string name="ftue_auth_carousel_2_title">شما کنترل می‌کنید.</string>
<string name="ftue_auth_carousel_1_title">صاحب گفت‌وگوهایتان باشید.</string> <string name="ftue_auth_carousel_1_title">صاحب گفت‌وگوهایتان باشید.</string>
<string name="tooltip_attachment_location">هم‌رسانی مکان</string>
<string name="settings_enable_location_sharing">به کار انداختن هم‌رسانی مکان</string>
<string name="location_share_external">گشودن با</string>
<string name="location_share">هم‌رسانی مکان</string>
<string name="a11y_location_share_icon">هم‌رسانی مکان</string>
<string name="location_activity_title_preview">مکان</string>
<string name="location_activity_title_static_sharing">هم‌رسانی مکان</string>
<string name="closed_poll_option_title">نظرسنجی بسته</string>
<string name="open_poll_option_title">گشودن نظرسنجی</string>
<string name="poll_type_title">گونهٔ نظرسنجی</string>
<string name="edit_poll_button">ویرایش نظرسنجی</string>
<string name="edit_poll_title">ویرایش نظرسنجی</string>
<string name="poll_no_votes_cast">رأیی داده نشده</string>
<string name="room_profile_section_restore_security">بازیابی رمزنگاری</string>
<string name="sent_location">مکانش را هم‌رسانی کرد</string>
<string name="login_splash_create_account">ایجاد حساب</string>
<string name="ftue_auth_carousel_title_messaging">پیام‌رسانی برای گروهتان.</string>
<string name="attachment_type_location">مکان</string>
</resources> </resources>

View file

@ -3017,7 +3017,7 @@
<item quantity="other">Résultat final sur la base de %1$d votes</item> <item quantity="other">Résultat final sur la base de %1$d votes</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_not_voted"> <plurals name="poll_total_vote_count_before_ended_and_not_voted">
<item quantity="one">Aucun vote exprimé</item> <item quantity="one">%1$d vote exprimé. Votez pour voir les résultats</item>
<item quantity="other">%1$d votes exprimés. Votez pour voir les résultats</item> <item quantity="other">%1$d votes exprimés. Votez pour voir les résultats</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_voted"> <plurals name="poll_total_vote_count_before_ended_and_voted">
@ -3040,8 +3040,8 @@
<string name="legals_home_server_title">La politique de votre serveur daccueil</string> <string name="legals_home_server_title">La politique de votre serveur daccueil</string>
<string name="template_legals_application_title">Politique de ${app_name}</string> <string name="template_legals_application_title">Politique de ${app_name}</string>
<string name="analytics_opt_in_list_item_3">Vous pouvez désactiver ceci à tout moment dans les paramètres</string> <string name="analytics_opt_in_list_item_3">Vous pouvez désactiver ceci à tout moment dans les paramètres</string>
<string name="analytics_opt_in_list_item_2">Nous <b>ne</b> partageons <b>pas</b> dinformation avec des tierces parties</string> <string name="analytics_opt_in_list_item_2">Nous ne partageons <b>aucune</b> information avec des tiers</string>
<string name="analytics_opt_in_list_item_1">Nous <b>n</b>enregistrons ou ne profilons <b>aucune</b> donnée du compte</string> <string name="analytics_opt_in_list_item_1">Nous nenregistrons ou ne profilons <b>aucune</b> donnée du compte</string>
<string name="analytics_opt_in_content_link">ici</string> <string name="analytics_opt_in_content_link">ici</string>
<string name="analytics_opt_in_content">Aidez nous à identifier les problèmes et améliorer Element en envoyant des rapports dusage anonymes. Pour comprendre de quelle manière les gens utilisent Element sur plusieurs appareils, nous créeront un identifiant aléatoire commun à tous vos appareils. <string name="analytics_opt_in_content">Aidez nous à identifier les problèmes et améliorer Element en envoyant des rapports dusage anonymes. Pour comprendre de quelle manière les gens utilisent Element sur plusieurs appareils, nous créeront un identifiant aléatoire commun à tous vos appareils.
\n \n
@ -3061,8 +3061,41 @@
<string name="room_member_override_nick_color">Outrepasser la couleur du pseudo</string> <string name="room_member_override_nick_color">Outrepasser la couleur du pseudo</string>
<string name="login_splash_already_have_account">Jai déjà un compte</string> <string name="login_splash_already_have_account">Jai déjà un compte</string>
<string name="ftue_auth_carousel_4_title">Être vicTeams, ce nest pas Slack vous voulez.</string> <string name="ftue_auth_carousel_4_title">Être vicTeams, ce nest pas Slack vous voulez.</string>
<string name="ftue_auth_carousel_3_title">Se connecter avec qui vous voulez.</string> <string name="ftue_auth_carousel_3_title">Messagerie sécurisée.</string>
<string name="ftue_auth_carousel_2_title">Vous êtes aux commandes.</string> <string name="ftue_auth_carousel_2_title">Vous êtes aux commandes.</string>
<string name="ftue_auth_carousel_1_title">Contrôlez vos conversations.</string> <string name="ftue_auth_carousel_1_title">Contrôlez vos conversations.</string>
<string name="room_error_access_unauthorized">Vous nêtes pas autorisé à rejoindre ce salon</string> <string name="room_error_access_unauthorized">Vous nêtes pas autorisé à rejoindre ce salon</string>
<string name="ftue_auth_carousel_body_control">Choisissez où vos conversations sont stockées, vous avez le contrôle et êtes indépendant. Connecté via Matrix.</string>
<string name="room_unsupported_e2e_algorithm">Le chiffrement a été mal configuré ce qui vous empêche denvoyer des messages. Veuillez contacter un administrateur pour remettre le chiffrement en état de marche.</string>
<string name="tooltip_attachment_location">Partager la localisation</string>
<string name="labs_render_locations_in_timeline">Afficher les localisations de l\'utilisateur dans le temps</string>
<string name="settings_enable_location_sharing_summary">Une fois activé il vous sera possible d\'envoyer votre localisation dans n\'importe quel salon</string>
<string name="settings_enable_location_sharing">Activer le partage de localisation</string>
<string name="location_share_external">Ouvrir avec</string>
<string name="template_location_not_available_dialog_content">${app_name} n\'a pas pu accéder à votre localisation. Veuillez réessayer plus tard.</string>
<string name="template_location_not_available_dialog_title">${app_name} n\'a pas pu accéder à votre localisation</string>
<string name="location_share">Partager la localisation</string>
<string name="a11y_location_share_icon">Partager la localisation</string>
<string name="location_activity_title_preview">Localisation</string>
<string name="location_activity_title_static_sharing">Partager la localisation</string>
<string name="closed_poll_option_description">Les résultats ne sont dévoilés que lorsque vous terminez le sondage</string>
<string name="closed_poll_option_title">Sondage fermé</string>
<string name="open_poll_option_description">Les votants voient les résultats dès qu\'ils ont votés</string>
<string name="open_poll_option_title">Ouvrir le sondage</string>
<string name="poll_type_title">Type de sondage</string>
<string name="edit_poll_button">ÉDITER LE SONDAGE</string>
<string name="edit_poll_title">Éditer le sondage</string>
<string name="poll_no_votes_cast">Aucun vote exprimé</string>
<string name="a11y_trust_level_misconfigured">Niveau de confiance mal configuré</string>
<string name="encryption_misconfigured">Le chiffrement est mal configuré</string>
<string name="room_profile_section_restore_security">Restaurer le Chiffrement</string>
<string name="contact_admin_to_restore_encryption">Veuillez contacter un administrateur pour reconfigurer le chiffrement.</string>
<string name="encryption_has_been_misconfigured">Le chiffrement a été mal configuré.</string>
<string name="sent_location">On partagé leur localisation</string>
<string name="login_splash_create_account">Créer un compte</string>
<string name="ftue_auth_carousel_title_messaging">Messagerie pour votre équipe.</string>
<string name="ftue_auth_carousel_body_encrypted">Chiffré de bout en bout et aucun numéro de téléphone n\'est nécessaire. Pas de pubs ni de collecte de données.</string>
<string name="ftue_auth_carousel_body_secure">Communication indépendante et sécurisée qui vous donne le même niveau d\'intimité qu\'une discussion face-à-face dans votre maison.</string>
<string name="attachment_type_location">Localisation</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Le chiffrement a été mal configuré ce qui vous empêche d\'envoyer des messages. Cliquez pour ouvrir les paramètres.</string>
</resources> </resources>

View file

@ -777,7 +777,7 @@ Figyelmeztetés: ez a fájl törlésre kerülhet, ha az alkalmazást törli.</st
<string name="start_voice_call_prompt_msg">Biztos, hogy hanghívást akarsz indítani\?</string> <string name="start_voice_call_prompt_msg">Biztos, hogy hanghívást akarsz indítani\?</string>
<string name="start_video_call_prompt_msg">Biztos, hogy videóhívást akarsz indítani\?</string> <string name="start_video_call_prompt_msg">Biztos, hogy videóhívást akarsz indítani\?</string>
<string name="groups_list">Csoportok listája</string> <string name="groups_list">Csoportok listája</string>
<string name="room_participants_ban_prompt_msg">A felhasználó kitiltása kirúgja őt a szobából, és megakadályozza, hogy újra csatlakozhasson.</string> <string name="room_participants_ban_prompt_msg">A felhasználó kitiltása eltávolítja őt a szobából, és megakadályozza, hogy újra csatlakozhasson.</string>
<string name="room_settings_all_messages_noisy">Összes üzenet (hangos)</string> <string name="room_settings_all_messages_noisy">Összes üzenet (hangos)</string>
<string name="room_settings_all_messages">Összes üzenet</string> <string name="room_settings_all_messages">Összes üzenet</string>
<string name="room_settings_mention_only">Csak megemlítések</string> <string name="room_settings_mention_only">Csak megemlítések</string>
@ -1009,7 +1009,7 @@ Matrixban az üzenetek láthatósága hasonlít az e-mailre. Az üzenet törlés
<string name="settings_show_read_receipts">Olvasás visszajelzés megjelenítése</string> <string name="settings_show_read_receipts">Olvasás visszajelzés megjelenítése</string>
<string name="settings_show_read_receipts_summary">További információér kattints az olvasás visszaigazolásokra.</string> <string name="settings_show_read_receipts_summary">További információér kattints az olvasás visszaigazolásokra.</string>
<string name="settings_show_join_leave_messages">Be-, és kilépési események megjelenítése</string> <string name="settings_show_join_leave_messages">Be-, és kilépési események megjelenítése</string>
<string name="settings_show_join_leave_messages_summary">Meghívások, kirúgások és kitiltások nem változtak.</string> <string name="settings_show_join_leave_messages_summary">Meghívások, eltávolítások és kitiltások nem változtak.</string>
<string name="settings_show_avatar_display_name_changes_messages">Fiók események megjelenítése</string> <string name="settings_show_avatar_display_name_changes_messages">Fiók események megjelenítése</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">Avatar és név változásokat tartalmaz.</string> <string name="settings_show_avatar_display_name_changes_messages_summary">Avatar és név változásokat tartalmaz.</string>
<string name="settings_password">Jelszó</string> <string name="settings_password">Jelszó</string>
@ -2751,7 +2751,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
<string name="room_settings_room_read_history_dialog_subtitle">A üzenetek olvashatóságának változtatása csak az új üzenetekre lesz érvényes. A régi üzenetek láthatósága nem fog változni.</string> <string name="room_settings_room_read_history_dialog_subtitle">A üzenetek olvashatóságának változtatása csak az új üzenetekre lesz érvényes. A régi üzenetek láthatósága nem fog változni.</string>
<string name="settings_show_emoji_keyboard_summary">Az üzenet szerkesztőhöz emodzsi billentyűzet gomb hozzáadása</string> <string name="settings_show_emoji_keyboard_summary">Az üzenet szerkesztőhöz emodzsi billentyűzet gomb hozzáadása</string>
<string name="settings_show_emoji_keyboard">Emodzsi billentyűzet megjelenítése</string> <string name="settings_show_emoji_keyboard">Emodzsi billentyűzet megjelenítése</string>
<string name="settings_show_room_member_state_events_summary">Magába foglalja a meghívás/belépés/kilépés/kirúgás/kitiltás eseményt és profilkép/megjelenítési név változtatást.</string> <string name="settings_show_room_member_state_events_summary">Magába foglalja a meghívás/belépés/kilépés/eltávolítás/kitiltás eseményt és profilkép/megjelenítési név változtatást.</string>
<string name="settings_chat_effects_description">Használd a /confetti parancsot vagy küldj üzenetet ami ❄️-t vagy 🎉-t tartalmaz</string> <string name="settings_chat_effects_description">Használd a /confetti parancsot vagy küldj üzenetet ami ❄️-t vagy 🎉-t tartalmaz</string>
<string name="settings_chat_effects_title">Beszélgetés effektek megjelenítése</string> <string name="settings_chat_effects_title">Beszélgetés effektek megjelenítése</string>
<string name="settings_show_room_member_state_events">Szoba tagok státusz eseményeinek megjelenítése</string> <string name="settings_show_room_member_state_events">Szoba tagok státusz eseményeinek megjelenítése</string>
@ -3015,7 +3015,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
<item quantity="other">Eredmény %1$d szavazat alapján</item> <item quantity="other">Eredmény %1$d szavazat alapján</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_not_voted"> <plurals name="poll_total_vote_count_before_ended_and_not_voted">
<item quantity="one">Nem szavazott senki</item> <item quantity="one">%1$d leadott szavazat. Szavazz az eredmények megtekintéséhez</item>
<item quantity="other">%1$d leadott szavazat. Szavazz az eredmények megtekintéséhez</item> <item quantity="other">%1$d leadott szavazat. Szavazz az eredmények megtekintéséhez</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_voted"> <plurals name="poll_total_vote_count_before_ended_and_voted">
@ -3061,6 +3061,39 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
<string name="room_member_override_nick_color">Becenév színének megváltoztatása</string> <string name="room_member_override_nick_color">Becenév színének megváltoztatása</string>
<string name="login_splash_already_have_account">Már van fiókom</string> <string name="login_splash_already_have_account">Már van fiókom</string>
<string name="ftue_auth_carousel_4_title">Rázd fel a csoportjaidat.</string> <string name="ftue_auth_carousel_4_title">Rázd fel a csoportjaidat.</string>
<string name="ftue_auth_carousel_3_title">Lépj kapcsolatba bárkivel.</string> <string name="ftue_auth_carousel_3_title">Biztonságos üzenetküldés.</string>
<string name="ftue_auth_carousel_2_title">Te irányítasz.</string> <string name="ftue_auth_carousel_2_title">Te irányítasz.</string>
<string name="tooltip_attachment_location">Tartózkodási hely megosztása</string>
<string name="labs_render_locations_in_timeline">A felhasználó földrajzi helyzetének megjelenítése az idővonalon</string>
<string name="settings_enable_location_sharing_summary">A beállítás után bármelyik szobában megoszthatod a földrajzi helyzetedet</string>
<string name="settings_enable_location_sharing">Földrajzi hely megosztás engedélyezése</string>
<string name="location_share_external">Megnyitás ezzel</string>
<string name="template_location_not_available_dialog_content">${app_name} nem fér hozzá a helyadatodhoz. Próbáld újra később.</string>
<string name="template_location_not_available_dialog_title">${app_name} nem fér hozzá a földrajzi helyzetedhez</string>
<string name="location_share">Tartózkodási hely megosztása</string>
<string name="a11y_location_share_icon">Tartózkodási hely megosztása</string>
<string name="location_activity_title_preview">Földrajzi helyzet</string>
<string name="location_activity_title_static_sharing">Tartózkodási hely megosztása</string>
<string name="closed_poll_option_description">Az eredmény csak a szavazás végeztével válik láthatóvá</string>
<string name="closed_poll_option_title">Lezárt szavazás</string>
<string name="open_poll_option_description">A szavazók a szavazásuk után látják a szavazatokat</string>
<string name="open_poll_option_title">Szavazás megnyitása</string>
<string name="poll_type_title">Szavazás típusa</string>
<string name="edit_poll_button">SZAVAZÁS SZERKESZTÉSE</string>
<string name="edit_poll_title">Szavazás szerkesztése</string>
<string name="poll_no_votes_cast">Nem adtak le szavazatot</string>
<string name="a11y_trust_level_misconfigured">Megbízhatósági szint beállítási hiba</string>
<string name="encryption_misconfigured">A titkosítási beállítás hibás</string>
<string name="room_profile_section_restore_security">Titkosítás helyreállítása</string>
<string name="contact_admin_to_restore_encryption">Kérjük vedd fel a kapcsolatot az adminisztrátorral a titkosítás helyreállítása érdekében.</string>
<string name="encryption_has_been_misconfigured">A titkosítás beállítása hibás.</string>
<string name="sent_location">A földrajzi helyzetüket megosztották</string>
<string name="login_splash_create_account">Fiók létrehozása</string>
<string name="ftue_auth_carousel_title_messaging">Üzenetküldés a csoportodnak.</string>
<string name="ftue_auth_carousel_body_encrypted">Telefonszám nélkül végpontok között titkosított. Reklámok és adatbányászat nélkül.</string>
<string name="ftue_auth_carousel_body_control">Válaszd meg hol legyenek a beszélgetéseid tárolva, visszaadja az irányítást és függetlenné tesz. Csatlakozva a Matrixhoz.</string>
<string name="ftue_auth_carousel_body_secure">Biztonságos és független kommunikáció ami olyan biztonságos mintha valakivel négyszemközt beszélgetnél a házadban.</string>
<string name="attachment_type_location">Földrajzi helyzet</string>
<string name="room_unsupported_e2e_algorithm_as_admin">A titkosítás beállítása hibás így nem lehet üzenetet küldeni. Kattints a beállításokért.</string>
<string name="room_unsupported_e2e_algorithm">A titkosítás beállítása hibás így nem lehet üzenetet küldeni. Kérjük vedd fel a kapcsolatot az adminisztrátorral a titkosítás helyreállításához.</string>
</resources> </resources>

View file

@ -3006,7 +3006,40 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.</string>
<string name="room_member_override_nick_color">Ubah warna nama tampilan</string> <string name="room_member_override_nick_color">Ubah warna nama tampilan</string>
<string name="login_splash_already_have_account">Saya sudah punya akun</string> <string name="login_splash_already_have_account">Saya sudah punya akun</string>
<string name="ftue_auth_carousel_4_title">Bebaskan.</string> <string name="ftue_auth_carousel_4_title">Bebaskan.</string>
<string name="ftue_auth_carousel_3_title">Hubung dengan siapa pun.</string> <string name="ftue_auth_carousel_3_title">Perpesanan yang aman.</string>
<string name="ftue_auth_carousel_2_title">Anda dalam kendali.</string> <string name="ftue_auth_carousel_2_title">Anda dalam kendali.</string>
<string name="ftue_auth_carousel_1_title">Miliki percakapan Anda.</string> <string name="ftue_auth_carousel_1_title">Miliki percakapan Anda.</string>
<string name="tooltip_attachment_location">Bagikan lokasi</string>
<string name="labs_render_locations_in_timeline">Tampilkan lokasi pengguna di linimasa</string>
<string name="settings_enable_location_sharing_summary">Setelah diaktifkan Anda akan dapat mengirim lokasi Anda ke ruangan apa saja</string>
<string name="settings_enable_location_sharing">Aktifkan pembagian lokasi</string>
<string name="location_share_external">Buka dengan</string>
<string name="template_location_not_available_dialog_content">${app_name} tidak dapat mengakses lokasi Anda. Silakan coba lagi nanti.</string>
<string name="template_location_not_available_dialog_title">${app_name} tidak dapat mengakses lokasi Anda</string>
<string name="location_share">Bagikan lokasi</string>
<string name="a11y_location_share_icon">Bagikan lokasi</string>
<string name="location_activity_title_preview">Lokasi</string>
<string name="location_activity_title_static_sharing">Bagikan lokasi</string>
<string name="closed_poll_option_description">Hasil akan ditampilkan ketika Anda mengakhiri poll-nya</string>
<string name="closed_poll_option_title">Poll tertutup</string>
<string name="open_poll_option_description">Pemberi suara akan melihat hasilnya ketika telah memberikan suara</string>
<string name="open_poll_option_title">Buka poll</string>
<string name="poll_type_title">Tipe poll</string>
<string name="edit_poll_button">EDIT POLL</string>
<string name="edit_poll_title">Edit poll</string>
<string name="poll_no_votes_cast">Tidak ada suara</string>
<string name="a11y_trust_level_misconfigured">Tingkat kepercayaan dikonfigurasi dengan salah</string>
<string name="encryption_misconfigured">Enkripsi dikonfigurasi dengan salah</string>
<string name="room_profile_section_restore_security">Pulihkan Enkripsi</string>
<string name="contact_admin_to_restore_encryption">Mohon hubungi sebuah admin untuk memulihkan enkripsi ke status yang valid.</string>
<string name="encryption_has_been_misconfigured">Enkripsi telah dikonfigurasi dengan salah.</string>
<string name="sent_location">Membagikan lokasinya</string>
<string name="login_splash_create_account">Buat akun</string>
<string name="ftue_auth_carousel_title_messaging">Perpesanan untuk tim Anda.</string>
<string name="ftue_auth_carousel_body_encrypted">Terenkripsi secara ujung-ke-ujung dan tidak memerlukan nomor telepon. Tidak ada iklan atau penambangan data.</string>
<string name="ftue_auth_carousel_body_control">Anda pilih di mana percakapan Anda disimpan, memberikan Anda kendali dan kebebasan. Terhubung via Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Komunikasi aman dan independen yang memberikan tingkat privasi yang sama seperti percakapan wajah-ke-wajah di dalam rumah Anda sendiri.</string>
<string name="attachment_type_location">Lokasi</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Enkripsi telah dikonfigurasi dengan salah sehingga Anda tidak dapat mengirim pesan. Klik untuk membuka pengaturan.</string>
<string name="room_unsupported_e2e_algorithm">Enkripsi telah dikonfigurasi dengan salah sehingga Anda tidak dapat mengirim pesan. Mohon hubungi sebuah admin untuk memulihkan enkripsi ke status yang valid.</string>
</resources> </resources>

View file

@ -846,7 +846,7 @@
<item quantity="one">%d utente</item> <item quantity="one">%d utente</item>
<item quantity="other">%d utenti</item> <item quantity="other">%d utenti</item>
</plurals> </plurals>
<string name="room_participants_ban_prompt_msg">Bandire l\'utente lo espellerà dalla stanza e gli impedirà di rientrare.</string> <string name="room_participants_ban_prompt_msg">Bandire l\'utente lo rimuoverà da questa stanza e gli impedirà di rientrare.</string>
<plurals name="room_new_messages_notification"> <plurals name="room_new_messages_notification">
<item quantity="one">%d nuovo messaggio</item> <item quantity="one">%d nuovo messaggio</item>
<item quantity="other">%d nuovi messaggi</item> <item quantity="other">%d nuovi messaggi</item>
@ -1081,7 +1081,7 @@
<string name="settings_show_read_receipts">Mostra le conferme di lettura</string> <string name="settings_show_read_receipts">Mostra le conferme di lettura</string>
<string name="settings_show_read_receipts_summary">Clicca sulle conferme di lettura per vederne l\'elenco dettagliato.</string> <string name="settings_show_read_receipts_summary">Clicca sulle conferme di lettura per vederne l\'elenco dettagliato.</string>
<string name="settings_show_join_leave_messages">Mostra entrata ed uscita degli utenti</string> <string name="settings_show_join_leave_messages">Mostra entrata ed uscita degli utenti</string>
<string name="settings_show_join_leave_messages_summary">Inviti, butta fuori e ban non vengono considerati.</string> <string name="settings_show_join_leave_messages_summary">Inviti, rimozioni e ban non vengono considerati.</string>
<string name="settings_show_avatar_display_name_changes_messages">Mostra i cambiamenti degli account</string> <string name="settings_show_avatar_display_name_changes_messages">Mostra i cambiamenti degli account</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">Includi cambiamenti dell\'avatar e del nome visualizzato.</string> <string name="settings_show_avatar_display_name_changes_messages_summary">Includi cambiamenti dell\'avatar e del nome visualizzato.</string>
<string name="settings_password">Password</string> <string name="settings_password">Password</string>
@ -2333,7 +2333,7 @@
<item quantity="other">%d secondi</item> <item quantity="other">%d secondi</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events">Mostra eventi di stato dei membri della stanza</string> <string name="settings_show_room_member_state_events">Mostra eventi di stato dei membri della stanza</string>
<string name="settings_show_room_member_state_events_summary">Includi eventi di invito/entrata/uscita/kick/ban e modifiche di avatar/nome.</string> <string name="settings_show_room_member_state_events_summary">Includi eventi di invito/entrata/uscita/rimozione/ban e modifiche di avatar/nome.</string>
<string name="sent_a_poll">Sondaggio</string> <string name="sent_a_poll">Sondaggio</string>
<string name="sent_a_reaction">Reagito con: %s</string> <string name="sent_a_reaction">Reagito con: %s</string>
<string name="sent_verification_conclusion">Verifica conclusa</string> <string name="sent_verification_conclusion">Verifica conclusa</string>
@ -2946,7 +2946,7 @@
<string name="space_permissions_notice">Seleziona i ruoli necessari per cambiare varie parti dello spazio</string> <string name="space_permissions_notice">Seleziona i ruoli necessari per cambiare varie parti dello spazio</string>
<string name="space_settings_permissions_subtitle">Vedi e aggiorna i ruoli necessari per cambiare varie parti dello spazio.</string> <string name="space_settings_permissions_subtitle">Vedi e aggiorna i ruoli necessari per cambiare varie parti dello spazio.</string>
<string name="space_participants_unban_prompt_msg">Riammettere l\'utente gli permetterà di rientrare nello spazio.</string> <string name="space_participants_unban_prompt_msg">Riammettere l\'utente gli permetterà di rientrare nello spazio.</string>
<string name="space_participants_ban_prompt_msg">Bandire l\'utente lo espellerà da questo spazio e gli impedirà di rientrare.</string> <string name="space_participants_ban_prompt_msg">Bandire l\'utente lo rimuoverà da questo spazio e gli impedirà di rientrare.</string>
<string name="space_participants_remove_prompt_msg">buttando fuori l\'utente verrà rimosso da questo spazio. <string name="space_participants_remove_prompt_msg">buttando fuori l\'utente verrà rimosso da questo spazio.
\n \n
\nPer impedire che possa rientrare, dovresti invece bandirlo.</string> \nPer impedire che possa rientrare, dovresti invece bandirlo.</string>
@ -3006,7 +3006,7 @@
<item quantity="other">Risultato finale basato su %1$d voti</item> <item quantity="other">Risultato finale basato su %1$d voti</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_not_voted"> <plurals name="poll_total_vote_count_before_ended_and_not_voted">
<item quantity="one">Nessun voto</item> <item quantity="one">%1$d voto. Vota per vedere i risultati</item>
<item quantity="other">%1$d voti. Vota per vedere i risultati</item> <item quantity="other">%1$d voti. Vota per vedere i risultati</item>
</plurals> </plurals>
<plurals name="poll_total_vote_count_before_ended_and_voted"> <plurals name="poll_total_vote_count_before_ended_and_voted">
@ -3051,7 +3051,40 @@
<string name="room_member_override_nick_color">Sovrascrivi colore nick</string> <string name="room_member_override_nick_color">Sovrascrivi colore nick</string>
<string name="login_splash_already_have_account">Ho già un account</string> <string name="login_splash_already_have_account">Ho già un account</string>
<string name="ftue_auth_carousel_4_title">Riduci il carico ai team.</string> <string name="ftue_auth_carousel_4_title">Riduci il carico ai team.</string>
<string name="ftue_auth_carousel_3_title">Connettiti con chiunque.</string> <string name="ftue_auth_carousel_3_title">Messaggistica sicura.</string>
<string name="ftue_auth_carousel_2_title">Tu hai il controllo.</string> <string name="ftue_auth_carousel_2_title">Tu hai il controllo.</string>
<string name="ftue_auth_carousel_1_title">Prendi il controllo delle tue conversazioni.</string> <string name="ftue_auth_carousel_1_title">Prendi il controllo delle tue conversazioni.</string>
<string name="tooltip_attachment_location">Condividi posizione</string>
<string name="labs_render_locations_in_timeline">Mostra le posizioni dell\'utente nella linea temporale</string>
<string name="settings_enable_location_sharing_summary">Una volta attivata, potrai inviare la tua posizione in qualsiasi stanza</string>
<string name="settings_enable_location_sharing">Attiva condivisione posizione</string>
<string name="location_share_external">Apri con</string>
<string name="template_location_not_available_dialog_content">${app_name} non ha potuto rilevare la tua posizione. Riprova più tardi.</string>
<string name="template_location_not_available_dialog_title">${app_name} non ha potuto rilevare la tua posizione</string>
<string name="location_share">Condividi posizione</string>
<string name="a11y_location_share_icon">Condividi posizione</string>
<string name="location_activity_title_preview">Posizione</string>
<string name="location_activity_title_static_sharing">Condividi posizione</string>
<string name="closed_poll_option_description">I risultati verranno rivelati solo quando termini il sondaggio</string>
<string name="closed_poll_option_title">Sondaggio chiuso</string>
<string name="open_poll_option_description">I votanti vedono i risultati appena avranno votato</string>
<string name="open_poll_option_title">Apri sondaggio</string>
<string name="poll_type_title">Tipo sondaggio</string>
<string name="edit_poll_button">MODIFICA SONDAGGIO</string>
<string name="edit_poll_title">Modifica sondaggio</string>
<string name="poll_no_votes_cast">Nessun voto</string>
<string name="a11y_trust_level_misconfigured">Livello di fiducia configurato male</string>
<string name="encryption_misconfigured">La crittografia è configurata male</string>
<string name="room_profile_section_restore_security">Reimposta crittografia</string>
<string name="contact_admin_to_restore_encryption">Contatta un amministratore per reimpostare la crittografia ad uno stato valido.</string>
<string name="encryption_has_been_misconfigured">La crittografia è stata configurata male.</string>
<string name="sent_location">Ha condiviso la sua posizione</string>
<string name="login_splash_create_account">Crea account</string>
<string name="ftue_auth_carousel_title_messaging">Messaggistica per la tua squadra.</string>
<string name="ftue_auth_carousel_body_encrypted">Crittografia end-to-end e nessun numero di telefono richiesto. Niente pubblicità o raccolta di dati.</string>
<string name="ftue_auth_carousel_body_control">Scegli dove vengono tenute le tue conversazioni, dandoti controllo e indipendenza. Connesso via Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Comunicazioni sicure e indipendenti che ti danno lo stesso livello di riservatezza di una conversazione faccia a faccia in casa tua.</string>
<string name="attachment_type_location">Posizione</string>
<string name="room_unsupported_e2e_algorithm_as_admin">La crittografia è stata configurata male, perciò non puoi inviare messaggi. Clicca per aprire le impostazioni.</string>
<string name="room_unsupported_e2e_algorithm">La crittografia è stata configurata male, perciò non puoi inviare messaggi. Contatta l\'amministratore per reimpostare la crittografia ad uno stato valido.</string>
</resources> </resources>

View file

@ -819,7 +819,7 @@
<string name="option_take_video">Tirar vídeo</string> <string name="option_take_video">Tirar vídeo</string>
<string name="groups_list">Lista de Grupos</string> <string name="groups_list">Lista de Grupos</string>
<string name="call">Chamar</string> <string name="call">Chamar</string>
<string name="room_participants_ban_prompt_msg">Banir usuária(o) vai expulsá-la(o) desta sala e preveni-la(o) de se juntar de novo.</string> <string name="room_participants_ban_prompt_msg">Banir usuária(o) vai removê-la(o) desta sala e preveni-la(o) de se juntar de novo.</string>
<string name="room_settings_all_messages_noisy">Todas as mensagens (barulhento)</string> <string name="room_settings_all_messages_noisy">Todas as mensagens (barulhento)</string>
<string name="room_settings_all_messages">Todas as mensagens</string> <string name="room_settings_all_messages">Todas as mensagens</string>
<string name="room_settings_mention_only">Menções somente</string> <string name="room_settings_mention_only">Menções somente</string>
@ -1118,7 +1118,7 @@
<string name="settings_show_read_receipts">Mostrar recibos de leitura</string> <string name="settings_show_read_receipts">Mostrar recibos de leitura</string>
<string name="settings_show_read_receipts_summary">Clique nos recibos de leitura para uma lista detalhada.</string> <string name="settings_show_read_receipts_summary">Clique nos recibos de leitura para uma lista detalhada.</string>
<string name="settings_show_join_leave_messages">Mostrar eventos de juntar-se e sair</string> <string name="settings_show_join_leave_messages">Mostrar eventos de juntar-se e sair</string>
<string name="settings_show_join_leave_messages_summary">Convites, expulsões e bans são desafetados.</string> <string name="settings_show_join_leave_messages_summary">Convites, remoções e bans são desafetados.</string>
<string name="settings_show_avatar_display_name_changes_messages">Mostrar eventos de conta</string> <string name="settings_show_avatar_display_name_changes_messages">Mostrar eventos de conta</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">Inclui mudanças de avatar e nome de exibição.</string> <string name="settings_show_avatar_display_name_changes_messages_summary">Inclui mudanças de avatar e nome de exibição.</string>
<string name="startup_notification_fdroid_battery_optim_title">Conexão no Background</string> <string name="startup_notification_fdroid_battery_optim_title">Conexão no Background</string>
@ -2334,7 +2334,7 @@
<item quantity="one">%d segundo</item> <item quantity="one">%d segundo</item>
<item quantity="other">%d segundos</item> <item quantity="other">%d segundos</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events_summary">Inclui eventos de convite/juntar-se/saiu/expulsão/ban e mudanças de avatar/nome de exibição.</string> <string name="settings_show_room_member_state_events_summary">Inclui eventos de convidar/juntar-se/saiu/remover/ban e mudanças de avatar/nome de exibição.</string>
<string name="settings_emails_and_phone_numbers_title">Emails e números de telefone</string> <string name="settings_emails_and_phone_numbers_title">Emails e números de telefone</string>
<string name="settings_emails_and_phone_numbers_summary">Gerenciar emails e números de telefone linkados a sua conta Matrix</string> <string name="settings_emails_and_phone_numbers_summary">Gerenciar emails e números de telefone linkados a sua conta Matrix</string>
<string name="settings_text_message_sent_hint">Código</string> <string name="settings_text_message_sent_hint">Código</string>
@ -2956,7 +2956,7 @@
<string name="space_settings_permissions_subtitle">Veja e atualize os papéis requeridos para mudar várias partes do espaço.</string> <string name="space_settings_permissions_subtitle">Veja e atualize os papéis requeridos para mudar várias partes do espaço.</string>
<string name="space_settings_permissions_title">Permissões de espaço</string> <string name="space_settings_permissions_title">Permissões de espaço</string>
<string name="space_participants_unban_prompt_msg">Desbanir usuária(o) vai permiti-la(o) se juntar ao espaço de novo.</string> <string name="space_participants_unban_prompt_msg">Desbanir usuária(o) vai permiti-la(o) se juntar ao espaço de novo.</string>
<string name="space_participants_ban_prompt_msg">Banir usuária(o) vai expulsá-la(o) deste espaço e preveni-la de se juntar de novo.</string> <string name="space_participants_ban_prompt_msg">Banir usuária(o) vai removê-la(o) deste espaço e preveni-la de se juntar de novo.</string>
<string name="space_participants_remove_prompt_msg">expulsar usuária(o) vai removê-la(o) deste espaço. <string name="space_participants_remove_prompt_msg">expulsar usuária(o) vai removê-la(o) deste espaço.
\n \n
\nPara preveni-la(o) de se juntar de novo, você devia bani-la(o) em vez disso.</string> \nPara preveni-la(o) de se juntar de novo, você devia bani-la(o) em vez disso.</string>
@ -3061,7 +3061,40 @@
<string name="room_member_override_nick_color">Sobrepor cor de nick</string> <string name="room_member_override_nick_color">Sobrepor cor de nick</string>
<string name="login_splash_already_have_account">Eu já tenho uma conta</string> <string name="login_splash_already_have_account">Eu já tenho uma conta</string>
<string name="ftue_auth_carousel_4_title">Dê liberdade a times.</string> <string name="ftue_auth_carousel_4_title">Dê liberdade a times.</string>
<string name="ftue_auth_carousel_3_title">Conecte-se com qualquer pessoa.</string> <string name="ftue_auth_carousel_3_title">Mensageria segura.</string>
<string name="ftue_auth_carousel_2_title">Você está em controle.</string> <string name="ftue_auth_carousel_2_title">Você está em controle.</string>
<string name="ftue_auth_carousel_1_title">Tenha posse de suas conversas.</string> <string name="ftue_auth_carousel_1_title">Tenha posse de suas conversas.</string>
<string name="tooltip_attachment_location">Compartilhar localização</string>
<string name="labs_render_locations_in_timeline">Render localizações de usuária(o) na timeline</string>
<string name="settings_enable_location_sharing_summary">Uma vez habilitada você vai ser capaz de enviar sua localização a qualquer sala</string>
<string name="settings_enable_location_sharing">Habilitar compartilhamento de localização</string>
<string name="location_share_external">Abrir com</string>
<string name="template_location_not_available_dialog_content">${app_name} não pôde acessar sua localização. Por favor tente de novo mais tarde.</string>
<string name="template_location_not_available_dialog_title">${app_name} não pôde acessar sua localização</string>
<string name="location_share">Compartilhar localização</string>
<string name="a11y_location_share_icon">Compartilhar localização</string>
<string name="location_activity_title_preview">Localização</string>
<string name="location_activity_title_static_sharing">Compartilhar localização</string>
<string name="closed_poll_option_description">Resultados são somente revelados quando você termina a sondagem</string>
<string name="closed_poll_option_title">Sondagem fechada</string>
<string name="open_poll_option_description">Votantes veem resultados assim que elas(es) têm votado</string>
<string name="open_poll_option_title">Sondagem aberta</string>
<string name="poll_type_title">Tipo de sondagem</string>
<string name="edit_poll_button">EDITAR SONDAGEM</string>
<string name="edit_poll_title">Editar sondagem</string>
<string name="poll_no_votes_cast">Nenhum voto lançado</string>
<string name="a11y_trust_level_misconfigured">Nível de confiança malconfigurado</string>
<string name="encryption_misconfigured">Encriptação está malconfigurada</string>
<string name="room_profile_section_restore_security">Restaurar Encriptação</string>
<string name="contact_admin_to_restore_encryption">Por favor contacte um(a) admin para restaurar encriptação a um estado válido.</string>
<string name="sent_location">Compartilhou a localização dela(e)</string>
<string name="attachment_type_location">Localização</string>
<string name="encryption_has_been_misconfigured">Encriptação tem sido malconfigurada.</string>
<string name="login_splash_create_account">Criar conta</string>
<string name="ftue_auth_carousel_title_messaging">Mensageria para seu time.</string>
<string name="ftue_auth_carousel_body_encrypted">Encriptado ponta-a-ponta e nenhum número de telefone requerido. Sem publicidade ou datamining.</string>
<string name="ftue_auth_carousel_body_control">Escolha onde suas conversas são mantidas, dando-lhe controle e independência. Conectado via Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Comunicação segura e independente que lhe dá o mesmo nível de privacidade que conversa face-a-face em sua própria casa.</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Encriptação tem sido malconfigurada então você não pode enviar mensagens. Clique para abrir configurações.</string>
<string name="room_unsupported_e2e_algorithm">Encriptação tem sido malconfigurada então você não pode enviar mensagens. Por favor contacte um(a) admin para restaurar encriptação a um estado válido.</string>
</resources> </resources>

View file

@ -795,7 +795,7 @@
<string name="start_voice_call_prompt_msg">Ste si istý, že chcete začať hlasový hovor?</string> <string name="start_voice_call_prompt_msg">Ste si istý, že chcete začať hlasový hovor?</string>
<string name="start_video_call_prompt_msg">Ste si istí, že chcete začať video hovor?</string> <string name="start_video_call_prompt_msg">Ste si istí, že chcete začať video hovor?</string>
<string name="groups_list">Zoznam komunít</string> <string name="groups_list">Zoznam komunít</string>
<string name="room_participants_ban_prompt_msg">Zakázanie používateľa ho vylúči z tejto miestnosti a zabráni mu v ďalšom vstupe.</string> <string name="room_participants_ban_prompt_msg">Zakázanie používateľa ho odstráni z tejto miestnosti a zabráni mu v ďalšom vstupe.</string>
<string name="room_settings_all_messages_noisy">Všetky správy (hlasné)</string> <string name="room_settings_all_messages_noisy">Všetky správy (hlasné)</string>
<string name="room_settings_all_messages">Všetky správy</string> <string name="room_settings_all_messages">Všetky správy</string>
<string name="room_settings_mention_only">Len zmienky</string> <string name="room_settings_mention_only">Len zmienky</string>
@ -2176,4 +2176,106 @@
<string name="notice_room_server_acl_set_ip_literals_allowed">• Servery s číslicami ako IP adresy sú povolené.</string> <string name="notice_room_server_acl_set_ip_literals_allowed">• Servery s číslicami ako IP adresy sú povolené.</string>
<string name="notice_room_server_acl_set_allowed">• Servery, ktorých názov sa zhoduje s %s sú povolené.</string> <string name="notice_room_server_acl_set_allowed">• Servery, ktorých názov sa zhoduje s %s sú povolené.</string>
<string name="notice_room_server_acl_set_banned">• Servery, ktorých názov sa zhoduje s %s sú zakázané.</string> <string name="notice_room_server_acl_set_banned">• Servery, ktorých názov sa zhoduje s %s sú zakázané.</string>
<string name="power_level_edit_title">Nastaviť rolu</string>
<string name="recovery_passphrase">Fráza pre obnovenie</string>
<string name="settings_category_composer">Editor správ</string>
<string name="verification_scan_emoji_title">Nedá sa skenovať</string>
<string name="devices_other_devices">Iné relácie</string>
<string name="devices_current_device">Aktuálna relácia</string>
<string name="soft_logout_clear_data_dialog_title">Vyčistiť údaje</string>
<string name="soft_logout_clear_data_dialog_submit">Vyčistiť údaje</string>
<string name="legals_third_party_notices">Knižnice tretích strán</string>
<string name="preference_help_title">Pomoc a podpora</string>
<string name="invite_by_username_or_mail">Pozvať pomocou používateľského mena alebo e-mailu</string>
<string name="labs_enable_latex_maths">Povoliť matematiku LaTeX</string>
<string name="restart_the_application_to_apply_changes">Reštartujte aplikáciu, aby sa zmena prejavila.</string>
<string name="ftue_auth_carousel_2_title">Vy máte všetko pod kontrolou.</string>
<string name="ftue_auth_carousel_3_title">Bezpečné zasielanie správ.</string>
<string name="labs_auto_report_uisi">Automatické hlásenie chýb dešifrovania.</string>
<string name="labs_auto_report_uisi_desc">Váš systém bude automaticky odosielať záznamy, keď sa vyskytne chyba dešifrovania</string>
<string name="tooltip_attachment_photo">Otvoriť kameru</string>
<string name="tooltip_attachment_gallery">Posielajte obrázky a videá</string>
<string name="tooltip_attachment_sticker">Odoslať nálepku</string>
<string name="tooltip_attachment_contact">Otvoriť kontakty</string>
<string name="tooltip_attachment_poll">Vytvoriť anketu</string>
<string name="ftue_auth_carousel_body_secure">Bezpečná a nezávislá komunikácia, ktorá vám poskytuje rovnakú úroveň súkromia ako rozhovor zoči-voči vo vašom vlastnom dome.</string>
<string name="ftue_auth_carousel_body_control">Vyberte si, kde budú vaše rozhovory uložené, a získajte tak kontrolu a nezávislosť. Pripojené cez Matrix.</string>
<string name="ftue_auth_carousel_body_encrypted">End-to-end šifrovanie a bez potreby telefónneho čísla. Žiadne reklamy ani zneužívanie údajov.</string>
<string name="ftue_auth_carousel_title_messaging">Zasielanie správ pre váš tím.</string>
<string name="login_splash_create_account">Vytvoriť účet</string>
<string name="encryption_has_been_misconfigured">Šifrovanie je nesprávne nastavené.</string>
<string name="contact_admin_to_restore_encryption">Obráťte sa na správcu, aby obnovil platný stav šifrovania.</string>
<string name="room_profile_section_restore_security">Obnoviť šifrovanie</string>
<string name="encryption_misconfigured">Šifrovanie je nesprávne nastavené</string>
<string name="poll_no_votes_cast">Žiadne odovzdané hlasy</string>
<string name="edit_poll_title">Upraviť anketu</string>
<string name="closed_poll_option_description">Výsledky sa zobrazia až po ukončení ankety</string>
<string name="attachment_type_location">Poloha</string>
<string name="sent_location">Zdieľali svoju polohu</string>
<string name="location_activity_title_static_sharing">Zdieľať polohu</string>
<string name="location_activity_title_preview">Poloha</string>
<string name="a11y_location_share_icon">Zdieľať polohu</string>
<string name="location_share">Zdieľať polohu</string>
<string name="template_location_not_available_dialog_title">${app_name} nemohol získať prístup k vašej polohe</string>
<string name="template_location_not_available_dialog_content">${app_name} nemohol získať prístup k vašej polohe. Skúste to prosím neskôr.</string>
<string name="location_share_external">Otvoriť s</string>
<string name="settings_enable_location_sharing">Povoliť zdieľanie polohy</string>
<string name="settings_enable_location_sharing_summary">Po zapnutí tejto funkcie budete môcť odoslať svoju polohu do ľubovoľnej miestnosti</string>
<string name="labs_render_locations_in_timeline">Vykresliť umiestnenie používateľa na časovej osi</string>
<string name="tooltip_attachment_location">Zdieľať polohu</string>
<string name="login_server_url_form_modular_text">Prémiový hosting pre organizácie</string>
<string name="login_signin_to">Prihlásiť sa do %1$s</string>
<string name="login_connect_to_a_custom_server">Pripojiť sa k vlastnému serveru</string>
<string name="login_connect_to_modular">Pripojiť sa k službám Element Matrix</string>
<string name="login_connect_to">Pripojiť sa k %1$s</string>
<string name="login_server_modular_text">Prémiový hosting pre organizácie</string>
<string name="login_server_matrix_org_text">Pripojte sa k miliónom ľudí zadarmo na najväčšom verejnom serveri</string>
<string name="login_server_text">Rovnako ako e-mail, aj účty majú jeden domov, hoci môžete hovoriť s kýmkoľvek</string>
<string name="login_splash_submit">Začnite</string>
<string name="login_splash_text3">Rozšírte a prispôsobte si možnosti</string>
<string name="login_splash_text2">Udržujte konverzácie súkromné pomocou šifrovania</string>
<string name="login_splash_text1">Komunikujte s ľuďmi priamo alebo v skupinách</string>
<string name="login_splash_title">Je to vaša konverzácia. Vlastnite ju.</string>
<string name="room_join_rules_invite_by_you">Vytvorili ste miestnosť len pre pozvaných.</string>
<string name="room_join_rules_invite">%1$s vytvoril miestnosť len na pozvanie.</string>
<string name="room_join_rules_public_by_you">Miestnosť ste zverejnili pre každého, kto pozná odkaz.</string>
<string name="room_join_rules_public">%1$s zverejnil miestnosť pre každého, kto pozná odkaz.</string>
<string name="help_long_click_on_room_for_more_options">Dlhým kliknutím na miestnosť zobrazíte ďalšie možnosti</string>
<string name="notice_member_no_changes_by_you">Nevykonali ste žiadne zmeny</string>
<string name="notice_member_no_changes">%1$s nevykonal žiadne zmeny</string>
<string name="content_reported_as_spam_content">Tento obsah bol nahlásený ako spam.
\n
\nAk nechcete vidieť ďalší obsah od tohto používateľa, môžete ho ignorovať a skryť jeho správy.</string>
<string name="content_reported_as_spam_title">Nahlásené ako spam</string>
<string name="content_reported_content">Tento obsah bol nahlásený.
\n
\nAk nechcete vidieť ďalší obsah od tohto používateľa, môžete ho ignorovať a skryť jeho správy.</string>
<string name="report_content_custom_submit">NAHLÁSIŤ</string>
<string name="report_content_custom_hint">Dôvod nahlásenia tohto obsahu</string>
<string name="uploads_files_no_result">V tejto miestnosti nie sú žiadne súbory</string>
<string name="uploads_media_title">MÉDIÁ</string>
<string name="uploads_media_no_result">V tejto miestnosti nie sú žiadne médiá</string>
<string name="error_attachment">Pri načítavaní prílohy došlo k chybe.</string>
<string name="error_file_too_big">Súbor \'%1$s\' (%2$s) je príliš veľký na odoslanie. Limit je %3$s.</string>
<string name="a11y_jump_to_bottom">Prejsť na spodok</string>
<string name="a11y_create_room">Vytvoriť novú miestnosť</string>
<string name="a11y_create_direct_message">Vytvoriť novú priamu konverzáciu</string>
<string name="error_terms_not_accepted">Po prijatí podmienok domovského servera to skúste znova.</string>
<string name="space_settings_permissions_subtitle">Zobraziť a aktualizovať role potrebné na zmenu rôznych častí priestoru.</string>
<string name="room_settings_permissions_subtitle">Zobraziť a aktualizovať role potrebné na zmenu rôznych častí miestnosti.</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Šifrovanie bolo nesprávne nastavené, takže nemôžete odosielať správy. Kliknutím otvorte nastavenia.</string>
<string name="room_unsupported_e2e_algorithm">Šifrovanie bolo nesprávne nastavené, takže nemôžete odosielať správy. Obráťte sa na správcu, aby obnovil platný stav šifrovania.</string>
<string name="space_participants_unban_prompt_msg">Zrušenie zákazu používateľovi mu umožní znovu sa pripojiť do priestoru.</string>
<string name="space_participants_ban_prompt_msg">Zakázanie používateľa ho odstráni z tohto priestoru a zabráni mu v ďalšom vstupe.</string>
<string name="space_participants_remove_prompt_msg">Používateľ bude z tohto priestoru odstránený.
\n
\nAby ste mu zabránili v opätovnom pripojení, mali by ste ho zakázať.</string>
<string name="room_participants_leave_private_warning">Táto miestnosť nie je verejná. Bez pozvánky sa do nej nebudete môcť opätovne pripojiť.</string>
<string name="continue_anyway">Pokračovať aj tak</string>
<string name="permissions_denied_add_contact">Povoľte prístup ku kontaktom.</string>
<string name="permissions_denied_qr_code">Ak chcete skenovať QR kód, musíte povoliť prístup k fotoaparátu.</string>
<string name="call_ended_user_busy_description">Volaný používateľ je obsadený.</string>
<string name="call_ended_user_busy_title">Používateľ je obsadený</string>
<string name="call_held_by_user">%s podržal hovor</string>
<string name="audio_call_with_participant">Hlasový hovor s %s</string>
</resources> </resources>

View file

@ -500,7 +500,7 @@
<string name="room_participants_invite_search_another_user">ID Përdoruesi, Emër ose email-i</string> <string name="room_participants_invite_search_another_user">ID Përdoruesi, Emër ose email-i</string>
<string name="room_participants_action_mention">Përmendje</string> <string name="room_participants_action_mention">Përmendje</string>
<string name="room_participants_action_devices_list">Shfaq Listë Sesionesh</string> <string name="room_participants_action_devices_list">Shfaq Listë Sesionesh</string>
<string name="room_participants_ban_prompt_msg">Dëbimi i përdoruesit do ta përzërë atë nga kjo dhomë dhe do ti pengojë atij rihyrjen.</string> <string name="room_participants_ban_prompt_msg">Dëbimi i përdoruesit do ta heqë atë nga kjo dhomë dhe do ti pengojë atij rihyrjen.</string>
<string name="reason_hint">Arsye</string> <string name="reason_hint">Arsye</string>
<string name="room_participants_invite_prompt_msg">Jeni i sigurt se doni të ftohet %s te kjo fjalosje?</string> <string name="room_participants_invite_prompt_msg">Jeni i sigurt se doni të ftohet %s te kjo fjalosje?</string>
<string name="room_participants_invite_join_names">"%1$s, "</string> <string name="room_participants_invite_join_names">"%1$s, "</string>
@ -1048,7 +1048,7 @@
<string name="settings_inline_url_preview_summary">Parashihini lidhjet brenda fjalosjes, kur shërbyesi juaj home e mbulon këtë veçori.</string> <string name="settings_inline_url_preview_summary">Parashihini lidhjet brenda fjalosjes, kur shërbyesi juaj home e mbulon këtë veçori.</string>
<string name="settings_send_typing_notifs_summary">Lejojuni përdoruesve të tjerë të dinë se po shtypni.</string> <string name="settings_send_typing_notifs_summary">Lejojuni përdoruesve të tjerë të dinë se po shtypni.</string>
<string name="settings_send_markdown_summary">Formatojini mesazhet duke përdorur sintaksën Markdown përpara se të dërgohen. Kjo lejon formatim të thelluar, f.v., përdorimi i yllthit për ta shfaqur tekstin me të pjerrëta.</string> <string name="settings_send_markdown_summary">Formatojini mesazhet duke përdorur sintaksën Markdown përpara se të dërgohen. Kjo lejon formatim të thelluar, f.v., përdorimi i yllthit për ta shfaqur tekstin me të pjerrëta.</string>
<string name="settings_show_join_leave_messages_summary">Nuk prek ftesat, përzëniet dhe dëbimet.</string> <string name="settings_show_join_leave_messages_summary">Nuk prek ftesat, heqjet dhe dëbimet.</string>
<string name="template_startup_notification_privacy_message">${app_name}-i mund të xhirojë në prapaskenë që të administrojë njoftimet tuaja në rrugë të sigurt dhe privatisht. Kjo mund të ndikojë në harxhimin e baterisë.</string> <string name="template_startup_notification_privacy_message">${app_name}-i mund të xhirojë në prapaskenë që të administrojë njoftimet tuaja në rrugë të sigurt dhe privatisht. Kjo mund të ndikojë në harxhimin e baterisë.</string>
<string name="template_settings_opt_in_of_analytics_summary">${app_name}-i grumbullon të dhëna analitike anonime që të na lejojë ta përmirësojmë aplikacionin.</string> <string name="template_settings_opt_in_of_analytics_summary">${app_name}-i grumbullon të dhëna analitike anonime që të na lejojë ta përmirësojmë aplikacionin.</string>
<string name="template_settings_opt_in_of_analytics_prompt">Ju lutemi, aktivizoni analizat që të na ndihmoni të përmirësojmë ${app_name}-in.</string> <string name="template_settings_opt_in_of_analytics_prompt">Ju lutemi, aktivizoni analizat që të na ndihmoni të përmirësojmë ${app_name}-in.</string>
@ -2201,7 +2201,7 @@
<item quantity="other">%d sekonda</item> <item quantity="other">%d sekonda</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events">Shfaq akte gjendjeje përdoruesish të dhomës</string> <string name="settings_show_room_member_state_events">Shfaq akte gjendjeje përdoruesish të dhomës</string>
<string name="settings_show_room_member_state_events_summary">Përfshin akte ftimi/pjesëmarrjeje/ikjeje/përzënieje/dëbimi dhe ndryshime emri avatari/shfaqjeje.</string> <string name="settings_show_room_member_state_events_summary">Përfshin akte ftimi/pjesëmarrjeje/ikjeje/heqjeje/dëbimi dhe ndryshime emri avatari/shfaqjeje.</string>
<string name="settings_secure_backup_section_title">Kopjeruajtje e Sigurt</string> <string name="settings_secure_backup_section_title">Kopjeruajtje e Sigurt</string>
<string name="settings_secure_backup_manage">Administroni</string> <string name="settings_secure_backup_manage">Administroni</string>
<string name="settings_secure_backup_setup">Ujdisni Kopjeruajtje të Sigurt</string> <string name="settings_secure_backup_setup">Ujdisni Kopjeruajtje të Sigurt</string>
@ -2867,8 +2867,8 @@
<string name="call_tap_to_return">%1$s Prekeni që të kthehet</string> <string name="call_tap_to_return">%1$s Prekeni që të kthehet</string>
<string name="call_one_active">Thirrje aktive (%1$s) ·</string> <string name="call_one_active">Thirrje aktive (%1$s) ·</string>
<plurals name="call_active_status"> <plurals name="call_active_status">
<item quantity="one">Thirrje aktive</item> <item quantity="one">Thirrje aktive ·</item>
<item quantity="other">%1$d thirrje aktive</item> <item quantity="other">%1$d thirrje aktive ·</item>
</plurals> </plurals>
<string name="call_tile_connection_failed">Lidhja dështoi</string> <string name="call_tile_connection_failed">Lidhja dështoi</string>
<string name="call_tile_no_answer">Ska përgjigje</string> <string name="call_tile_no_answer">Ska përgjigje</string>
@ -2913,7 +2913,7 @@
<string name="you_will_leave_all_in">Do të braktisni krejt dhomat dhe hapësirat te %s.</string> <string name="you_will_leave_all_in">Do të braktisni krejt dhomat dhe hapësirat te %s.</string>
<string name="leave_all_rooms_and_spaces">Braktis krejt dhomat dhe hapësirat</string> <string name="leave_all_rooms_and_spaces">Braktis krejt dhomat dhe hapësirat</string>
<string name="space_leave_prompt_msg_with_name">Jeni i sigurt se doni të dilni nga \'%s\?</string> <string name="space_leave_prompt_msg_with_name">Jeni i sigurt se doni të dilni nga \'%s\?</string>
<string name="discovery_section">Zbulim (%S)</string> <string name="discovery_section">Zbulim (%s)</string>
<string name="finish_setup">Përfundoje ujdisjen</string> <string name="finish_setup">Përfundoje ujdisjen</string>
<string name="discovery_invite">Ftoni me email, gjeni kontakte, etj…</string> <string name="discovery_invite">Ftoni me email, gjeni kontakte, etj…</string>
<string name="finish_setting_up_discovery">Përfundo ujdisjen e zbulimit.</string> <string name="finish_setting_up_discovery">Përfundo ujdisjen e zbulimit.</string>
@ -2945,7 +2945,7 @@
<string name="space_settings_permissions_subtitle">Të shohë dhe përditësojë role të domosdoshëm për të ndryshuar anë të ndryshme të hapësirës.</string> <string name="space_settings_permissions_subtitle">Të shohë dhe përditësojë role të domosdoshëm për të ndryshuar anë të ndryshme të hapësirës.</string>
<string name="space_settings_permissions_title">Leje hapësire</string> <string name="space_settings_permissions_title">Leje hapësire</string>
<string name="space_participants_unban_prompt_msg">Heqja e dëbimit përdoruesit do ti lejojë të marrë pjesë sërish në hapësirë.</string> <string name="space_participants_unban_prompt_msg">Heqja e dëbimit përdoruesit do ti lejojë të marrë pjesë sërish në hapësirë.</string>
<string name="space_participants_ban_prompt_msg">Dëbimi i përdoruesit do ta përzërë atë nga kjo hapësirë dhe do ti pengojë atij rihyrjen.</string> <string name="space_participants_ban_prompt_msg">Dëbimi i përdoruesit do ta heqë atë nga kjo hapësirë dhe do ti pengojë atij rihyrjen.</string>
<string name="space_participants_remove_prompt_msg">Përzënia e përdoruesit do ta heqë prej kësaj hapësire. <string name="space_participants_remove_prompt_msg">Përzënia e përdoruesit do ta heqë prej kësaj hapësire.
\n \n
\nQë të pengohet pjesëmarrja sërish e tij, duhet ta dëboni.</string> \nQë të pengohet pjesëmarrja sërish e tij, duhet ta dëboni.</string>
@ -3032,8 +3032,8 @@
<string name="analytics_opt_in_title">Ndihmoni të përmirësohet Element-in</string> <string name="analytics_opt_in_title">Ndihmoni të përmirësohet Element-in</string>
<string name="action_enable">Aktivizoje</string> <string name="action_enable">Aktivizoje</string>
<plurals name="poll_total_vote_count_before_ended_and_not_voted"> <plurals name="poll_total_vote_count_before_ended_and_not_voted">
<item quantity="one">Ska vota të hedhura</item> <item quantity="one">%1$d votë e hedhur. Votoni, që të shihni përfundimet</item>
<item quantity="other">%1$d votë e hedhur. Votoni, që të shihni përfundimet</item> <item quantity="other">%1$d vota të hedhur. Votoni, që të shihni përfundimet</item>
</plurals> </plurals>
<string name="restart_the_application_to_apply_changes">Që ndryshimi të hyjë në fuqi, rinisni aplikacionin.</string> <string name="restart_the_application_to_apply_changes">Që ndryshimi të hyjë në fuqi, rinisni aplikacionin.</string>
<string name="labs_enable_latex_maths">Aktivizo elementë LaTeX për matematikë</string> <string name="labs_enable_latex_maths">Aktivizo elementë LaTeX për matematikë</string>
@ -3048,7 +3048,40 @@
<string name="labs_auto_report_uisi">Raporto Vetvetiu Gabime Shfshehtëzimi.</string> <string name="labs_auto_report_uisi">Raporto Vetvetiu Gabime Shfshehtëzimi.</string>
<string name="room_member_override_nick_color">Anashkalo ngjyrë nofke</string> <string name="room_member_override_nick_color">Anashkalo ngjyrë nofke</string>
<string name="login_splash_already_have_account">Kam tashmë një llogari</string> <string name="login_splash_already_have_account">Kam tashmë një llogari</string>
<string name="ftue_auth_carousel_3_title">Lidhuni me këdo.</string> <string name="ftue_auth_carousel_3_title">Shkëmbim i siguruar mesazhesh.</string>
<string name="ftue_auth_carousel_2_title">Kontrollin e keni ju.</string> <string name="ftue_auth_carousel_2_title">Kontrollin e keni ju.</string>
<string name="ftue_auth_carousel_1_title">Jini zot i bisedave tuaja.</string> <string name="ftue_auth_carousel_1_title">Jini zot i bisedave tuaja.</string>
<string name="tooltip_attachment_location">Jepe vendndodhjen</string>
<string name="settings_enable_location_sharing">Aktivizoni dhënie vendndodhjeje</string>
<string name="location_share">Jepe vendndodhjen</string>
<string name="a11y_location_share_icon">Jepe vendndodhjen</string>
<string name="location_activity_title_preview">Vendndodhje</string>
<string name="location_activity_title_static_sharing">Jepe vendndodhjen</string>
<string name="closed_poll_option_description">Përfundimet shfaqen vetëm kur përfundoni anketimin</string>
<string name="closed_poll_option_title">Anketim i mbyllur</string>
<string name="open_poll_option_description">Votuesit do të shohin përfundime sapo të kenë votuar</string>
<string name="open_poll_option_title">Anketim i hapur</string>
<string name="poll_type_title">Lloj anketimi</string>
<string name="login_splash_create_account">Krijoni llogari</string>
<string name="ftue_auth_carousel_title_messaging">Shkëmbim mesazhesh për ekipin tuaj.</string>
<string name="ftue_auth_carousel_body_encrypted">I fshehtëzuar skaj më skaj dhe pa u dashur numër telefoni. Pa reklama, apo shfrytëzim të dhënash.</string>
<string name="ftue_auth_carousel_body_control">Zgjidhni ku mbahen bisedat tuaja, duke ju dhënë kontroll dhe pavarësi. Të lidhur përmes Matrix-i.</string>
<string name="ftue_auth_carousel_body_secure">Komunikim i sigurt dhe i pavarur, që ju jep të njëjtën shkallë privatësie si biseda kokë më kokë, në shtëpinë tuaj.</string>
<string name="labs_render_locations_in_timeline">Trego vendndodhje përdoruesi në rrjedhën kohore</string>
<string name="settings_enable_location_sharing_summary">Pasi të aktivizohet, do të jeni në gjendje të dërgoni vendndodhjen tuaj në çfarëdo dhome</string>
<string name="location_share_external">Hape me</string>
<string name="template_location_not_available_dialog_content">${app_name} snjohu dot vendndodhjen tuaj. Ju lutemi, riprovoni më vonë.</string>
<string name="template_location_not_available_dialog_title">${app_name} smësoi dot vendndodhjen tuaj</string>
<string name="edit_poll_button">PËRPUNONI ANKETIMIN</string>
<string name="edit_poll_title">Përpunoni anketimin</string>
<string name="poll_no_votes_cast">Sjanë hedhur vota</string>
<string name="a11y_trust_level_misconfigured">Shkallë besueshmërie e formësuar gabim</string>
<string name="encryption_misconfigured">Fshehtëzimi është formësuar gabim</string>
<string name="room_profile_section_restore_security">Riktheni Fshehtëzimin</string>
<string name="contact_admin_to_restore_encryption">Ju lutemi, lidhuni me një nga përgjegjësit, që ta ktheni fshehtëzimin në një gjendje të vlefshme.</string>
<string name="encryption_has_been_misconfigured">Fshehtëzimi është formësuar gabim.</string>
<string name="sent_location">Tregoi vendndodhjen e vet</string>
<string name="attachment_type_location">Vendndodhje</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Fshehtëzimi është formësuar keq, që të mos dërgoni mesazhe. Klikoni që të hapni rregullimet.</string>
<string name="room_unsupported_e2e_algorithm">Fshehtëzimi është formësuar keq, që të mos dërgoni mesazhe. Ju lutemi, lidhuni me një nga përgjegjësit që ta ktheni fshehtëzimin në një gjendje të vlefshme.</string>
</resources> </resources>

View file

@ -37,7 +37,7 @@
<string name="view_decrypted_source">Deşifre Edilmiş Kaynağı İncele</string> <string name="view_decrypted_source">Deşifre Edilmiş Kaynağı İncele</string>
<string name="action_delete">Sil</string> <string name="action_delete">Sil</string>
<string name="action_rename">Yeniden Adlandır</string> <string name="action_rename">Yeniden Adlandır</string>
<string name="report_content">İçeriği bildir</string> <string name="report_content">Rapor İçeriği</string>
<string name="active_call">Şu anki görüşme</string> <string name="active_call">Şu anki görüşme</string>
<string name="ongoing_conference_call">Devam eden konferans görüşmesi. <string name="ongoing_conference_call">Devam eden konferans görüşmesi.
\n%1$s veya %2$s olarak katıl</string> \n%1$s veya %2$s olarak katıl</string>
@ -118,7 +118,7 @@
<string name="create_account">Hesap oluştur</string> <string name="create_account">Hesap oluştur</string>
<string name="login">Giriş yap</string> <string name="login">Giriş yap</string>
<string name="logout">Çıkış yap</string> <string name="logout">Çıkış yap</string>
<string name="hs_url">Ev Sunucusu URL\'si</string> <string name="hs_url">Ana Sunucu URL\'si</string>
<string name="search">Ara</string> <string name="search">Ara</string>
<string name="start_new_chat">Yeni Sohbete Başla</string> <string name="start_new_chat">Yeni Sohbete Başla</string>
<string name="start_voice_call">Sesli Görüşme Başlat</string> <string name="start_voice_call">Sesli Görüşme Başlat</string>
@ -188,7 +188,7 @@
<string name="dialog_title_error">Hata</string> <string name="dialog_title_error">Hata</string>
<string name="system_alerts_header">Sistem Uyarıları</string> <string name="system_alerts_header">Sistem Uyarıları</string>
<string name="send_files_in">Gönder</string> <string name="send_files_in">Gönder</string>
<string name="identity_url">Kimlik Sunucusu URL\'si</string> <string name="identity_url">Kimlik sunucusu URL\'si</string>
<string name="auth_email_placeholder">E-posta adresi</string> <string name="auth_email_placeholder">E-posta adresi</string>
<string name="auth_opt_email_placeholder">E-posta adresi (isteğe bağlı)</string> <string name="auth_opt_email_placeholder">E-posta adresi (isteğe bağlı)</string>
<string name="auth_phone_number_placeholder">Telefon numarası</string> <string name="auth_phone_number_placeholder">Telefon numarası</string>
@ -213,10 +213,10 @@
<string name="auth_threepid_warning_message">Eposta ve telefon numarası ile aynı anda kayıt yaptırmak şimdilik API yüzüden desteklenmiyor. Sadece telefon numarası hesaba eklenecektir. <string name="auth_threepid_warning_message">Eposta ve telefon numarası ile aynı anda kayıt yaptırmak şimdilik API yüzüden desteklenmiyor. Sadece telefon numarası hesaba eklenecektir.
\n \n
\nEpostanı daha sonra profil ayarlarından ekleyebilirsin.</string> \nEpostanı daha sonra profil ayarlarından ekleyebilirsin.</string>
<string name="auth_recaptcha_message">Ana Makine senin robot olmadığından emin olmak istiyor</string> <string name="auth_recaptcha_message">Bu ana sunucu bir robot olmadığından emin olmak istiyor</string>
<string name="auth_username_in_use">Kullandığın kullanıcı adı</string> <string name="auth_username_in_use">Kullandığın kullanıcı adı</string>
<string name="auth_home_server">Ana Makine:</string> <string name="auth_home_server">Ana sunucu:</string>
<string name="auth_identity_server">Tanımlayıcı Sunucu:</string> <string name="auth_identity_server">Kimlik sunucusu:</string>
<string name="auth_reset_password_next_step_button">Eposta adresimi doğruladım</string> <string name="auth_reset_password_next_step_button">Eposta adresimi doğruladım</string>
<string name="auth_reset_password_message">Şifrenizi sıfırlamak için, hesabınıza bağlı eposta adresini girin:</string> <string name="auth_reset_password_message">Şifrenizi sıfırlamak için, hesabınıza bağlı eposta adresini girin:</string>
<string name="auth_reset_password_missing_email">Hesaba bağlı eposta adresi mutlaka girilmeli.</string> <string name="auth_reset_password_missing_email">Hesaba bağlı eposta adresi mutlaka girilmeli.</string>
@ -248,8 +248,8 @@
<string name="read_receipts_list">Makbuz Listesini Oku</string> <string name="read_receipts_list">Makbuz Listesini Oku</string>
<string name="groups_list">Grup Listesi</string> <string name="groups_list">Grup Listesi</string>
<plurals name="membership_changes"> <plurals name="membership_changes">
<item quantity="one">1 üyelik değişimi</item> <item quantity="one">%d üyelik değişikliği</item>
<item quantity="other">%d üyelik değişimi</item> <item quantity="other">%d üyelik değişiklikleri</item>
</plurals> </plurals>
<string name="compression_options">Farklı gönder</string> <string name="compression_options">Farklı gönder</string>
<string name="compression_opt_list_original">Orijinal</string> <string name="compression_opt_list_original">Orijinal</string>
@ -325,28 +325,28 @@
<string name="room_creation_title">Yeni Sohbet</string> <string name="room_creation_title">Yeni Sohbet</string>
<string name="room_creation_add_member">Üye ekle</string> <string name="room_creation_add_member">Üye ekle</string>
<plurals name="room_header_active_members_count"> <plurals name="room_header_active_members_count">
<item quantity="one">1 aktif üye</item> <item quantity="one">%d aktif üye</item>
<item quantity="other">%d aktif üye</item> <item quantity="other">%d aktif üyeler</item>
</plurals> </plurals>
<plurals name="room_title_members"> <plurals name="room_title_members">
<item quantity="one">1 üye</item> <item quantity="one">%d üye</item>
<item quantity="other">%d üye</item> <item quantity="other">%d üyeler</item>
</plurals> </plurals>
<string name="room_title_one_member">1 üye</string> <string name="room_title_one_member">1 üye</string>
<plurals name="format_time_s"> <plurals name="format_time_s">
<item quantity="one">1sn</item> <item quantity="one">%ds 1</item>
<item quantity="other">%dsn</item> <item quantity="other">%ds</item>
</plurals> </plurals>
<plurals name="format_time_m"> <plurals name="format_time_m">
<item quantity="one">1dk</item> <item quantity="one">%ddk</item>
<item quantity="other">%ddk</item> <item quantity="other">%ddk</item>
</plurals> </plurals>
<plurals name="format_time_h"> <plurals name="format_time_h">
<item quantity="one">1sa</item> <item quantity="one">%dsa</item>
<item quantity="other">%dsa</item> <item quantity="other">%dsa</item>
</plurals> </plurals>
<plurals name="format_time_d"> <plurals name="format_time_d">
<item quantity="one">1g</item> <item quantity="one">%dg</item>
<item quantity="other">%dg</item> <item quantity="other">%dg</item>
</plurals> </plurals>
<string name="room_participants_leave_prompt_title">Odadan ayrıl</string> <string name="room_participants_leave_prompt_title">Odadan ayrıl</string>
@ -376,7 +376,7 @@
<string name="room_participants_action_devices_list">Oturum Listesini Göster</string> <string name="room_participants_action_devices_list">Oturum Listesini Göster</string>
<string name="room_participants_power_level_prompt">Bu işlemin geri dönüşü yok kullanıcıyı sen ile aynı erişim seviyesine getiriyorsun. <string name="room_participants_power_level_prompt">Bu işlemin geri dönüşü yok kullanıcıyı sen ile aynı erişim seviyesine getiriyorsun.
\nEmin misin\?</string> \nEmin misin\?</string>
<string name="room_participants_ban_prompt_msg">Kullanıcıyı bu engellersen bu odadan kovulacak ve bir daha giremeyecek.</string> <string name="room_participants_ban_prompt_msg">Kullanıcıyı yasaklamak onları bu odadan çıkaracak ve tekrar katılmalarını engelleyecektir.</string>
<string name="reason_hint">Neden</string> <string name="reason_hint">Neden</string>
<string name="room_participants_invite_prompt_msg">%s adlı kullanıcılar(ı) bu sohbete davet etmek istediğinden emin misin\?</string> <string name="room_participants_invite_prompt_msg">%s adlı kullanıcılar(ı) bu sohbete davet etmek istediğinden emin misin\?</string>
<string name="room_participants_invite_join_names">"%1$s, "</string> <string name="room_participants_invite_join_names">"%1$s, "</string>
@ -405,10 +405,10 @@
<string name="room_resend_unsent_messages">Gönderilmeyen mesajları tekrar gönder</string> <string name="room_resend_unsent_messages">Gönderilmeyen mesajları tekrar gönder</string>
<string name="room_delete_unsent_messages">Gönderilmeyen mesajları sil</string> <string name="room_delete_unsent_messages">Gönderilmeyen mesajları sil</string>
<string name="room_message_file_not_found">Dosya bulunamadı</string> <string name="room_message_file_not_found">Dosya bulunamadı</string>
<string name="room_do_not_have_permission_to_post">Bu odada mesajlaşmaya yetkin yok</string> <string name="room_do_not_have_permission_to_post">Bu odaya mesaj gönderme izniniz yok.</string>
<plurals name="room_new_messages_notification"> <plurals name="room_new_messages_notification">
<item quantity="one">1 yeni mesaj</item> <item quantity="one">%d yeni mesaj</item>
<item quantity="other">%d yeni mesaj</item> <item quantity="other">%d yeni mesajlar</item>
</plurals> </plurals>
<string name="ssl_trust">Güven</string> <string name="ssl_trust">Güven</string>
<string name="ssl_do_not_trust">Güvenme</string> <string name="ssl_do_not_trust">Güvenme</string>
@ -426,7 +426,7 @@
<string name="room_details_files">Dosyalar</string> <string name="room_details_files">Dosyalar</string>
<string name="room_details_settings">Ayarlar</string> <string name="room_details_settings">Ayarlar</string>
<plurals name="room_details_selected"> <plurals name="room_details_selected">
<item quantity="one">1 tane seçili</item> <item quantity="one">%d tane seçili</item>
<item quantity="other">%d tane seçili</item> <item quantity="other">%d tane seçili</item>
</plurals> </plurals>
<string name="malformed_id">Hatalı ID. Eposta adresi ya da Matrix ID\'si olmalıdır \'@localpart:domain\'</string> <string name="malformed_id">Hatalı ID. Eposta adresi ya da Matrix ID\'si olmalıdır \'@localpart:domain\'</string>
@ -447,8 +447,8 @@
<string name="tab_title_search_files">DOSYALAR</string> <string name="tab_title_search_files">DOSYALAR</string>
<string name="directory_search_results_title">Dizinlere gözat</string> <string name="directory_search_results_title">Dizinlere gözat</string>
<plurals name="directory_search_rooms"> <plurals name="directory_search_rooms">
<item quantity="one">1 oda</item> <item quantity="one">%d oda</item>
<item quantity="other">%d oda</item> <item quantity="other">%d odalar</item>
</plurals> </plurals>
<plurals name="directory_search_rooms_for"> <plurals name="directory_search_rooms_for">
<item quantity="one">%2$s adında %1$s oda bulundu</item> <item quantity="one">%2$s adında %1$s oda bulundu</item>
@ -1068,7 +1068,7 @@
<string name="auth_add_email_and_phone_message_2">Hesap kurtarma epostası kaydedin. Daha sonra isteğe bağlı eposta veya telefon nuraması kullanarak sizi tanıyan kişilerin sizi bulabilmesini sağlayın.</string> <string name="auth_add_email_and_phone_message_2">Hesap kurtarma epostası kaydedin. Daha sonra isteğe bağlı eposta veya telefon nuraması kullanarak sizi tanıyan kişilerin sizi bulabilmesini sağlayın.</string>
<string name="login_error_ssl_handshake">Cihazın saldırılara açık, eski bir TLS güvenlik protokolü kullanıyor; güvenliğin için bağlantın engellendi</string> <string name="login_error_ssl_handshake">Cihazın saldırılara açık, eski bir TLS güvenlik protokolü kullanıyor; güvenliğin için bağlantın engellendi</string>
<string name="settings_call_ringtone_use_default_stun">İkincil çağrı yardımcı sunucusuna izin ver</string> <string name="settings_call_ringtone_use_default_stun">İkincil çağrı yardımcı sunucusuna izin ver</string>
<string name="settings_call_ringtone_use_default_stun_sum">Anasunucunuz çağrı yardımcı sunucusu vermez ise %s çağrı yardımcı sunucusu olarak kullanılacaktır (Çağrıda IP adresiniz paylaşılacaktır)</string> <string name="settings_call_ringtone_use_default_stun_sum">Ana sunucunuz bir tane sunmadığında %sas assist kullanacaktır (arama sırasında IP adresiniz paylaşılacaktır)</string>
<string name="invite_no_identity_server_error">Bu eylemi gerçekleştirebilmek için ayarlarınızdan bir kimlik sunucusu ekleyin.</string> <string name="invite_no_identity_server_error">Bu eylemi gerçekleştirebilmek için ayarlarınızdan bir kimlik sunucusu ekleyin.</string>
<string name="settings_add_3pid_confirm_password_title">Şifreni doğrula</string> <string name="settings_add_3pid_confirm_password_title">Şifreni doğrula</string>
<string name="template_settings_background_fdroid_sync_mode_battery_description">${app_name}, cihazın sınırlı kaynaklarını (pil) koruyacak şekilde arka planda senkronize olur. <string name="template_settings_background_fdroid_sync_mode_battery_description">${app_name}, cihazın sınırlı kaynaklarını (pil) koruyacak şekilde arka planda senkronize olur.
@ -1819,4 +1819,211 @@
<string name="notice_direct_room_update_by_you">Burada yükselttiniz.</string> <string name="notice_direct_room_update_by_you">Burada yükselttiniz.</string>
<string name="notice_room_visibility_joined">tüm oda üyeleri, katıldıkları andan itibaren.</string> <string name="notice_room_visibility_joined">tüm oda üyeleri, katıldıkları andan itibaren.</string>
<string name="notice_room_visibility_invited">tüm oda üyeleri, davet edildikleri andan itibaren.</string> <string name="notice_room_visibility_invited">tüm oda üyeleri, davet edildikleri andan itibaren.</string>
<string name="room_settings_none">Hiçbiri</string>
<string name="room_settings_mention_and_keyword_only">Yalnızca Söz ve Anahtar Kelimeler</string>
<string name="room_permissions_upgrade_the_space">Alanı yükseltin</string>
<string name="room_permissions_send_m_room_server_acl_events">m.room.server_acl olaylarını gönder</string>
<string name="room_permissions_change_space_name">Alan adını değiştir</string>
<string name="room_permissions_enable_space_encryption">Alan şifrelemeyi etkinleştir</string>
<string name="room_permissions_change_main_address_for_the_space">Alanın ana adresini değiştirme</string>
<string name="room_permissions_change_space_avatar">Alan avatarını değiştir</string>
<string name="space_permissions_notice_read_only">Bu alanın çeşitli bölümlerini değiştirmek için gereken rolleri güncelleme izniniz yok</string>
<string name="space_permissions_notice">Bu alanın çeşitli bölümlerini değiştirmek için gereken rolleri seçin</string>
<string name="space_settings_permissions_subtitle">Alanın çeşitli bölümlerini değiştirmek için gereken rolleri görüntüleyin ve güncelleyin.</string>
<string name="space_settings_permissions_title">Alan izinleri</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Şifreleme yanlış yapılandırıldı, böylece mesaj gönderemezsiniz. Ayarlar\'ı açmak için tıklatın.</string>
<string name="room_unsupported_e2e_algorithm">Şifreleme yanlış yapılandırıldı, böylece mesaj gönderemezsiniz. Şifrelemeyi geçerli bir duruma geri yüklemek için lütfen bir yöneticiyle iletişime geçin.</string>
<string name="space_participants_unban_prompt_msg">Yasağı kaldırmak, kullanıcının alana tekrar katılmasına izin verir.</string>
<string name="space_participants_ban_prompt_msg">Kullanıcıyı yasaklamak onları bu alandan kaldıracak ve tekrar katılmalarını engelleyecektir.</string>
<string name="space_participants_remove_prompt_msg">Kullanıcı bu alandan kaldırılacaktır.
\n
\nTekrar katılmalarını önlemek için, onları yasaklamalısınız.</string>
<string name="continue_anyway">Yine de Devam Et</string>
<string name="call_remove_jitsi_widget_progress">Arama sonlandırılıyor…</string>
<string name="call_ended_invite_timeout_title">Cevap yok</string>
<string name="call_ended_user_busy_description">Aradığınız kullanıcı meşgul.</string>
<string name="call_ended_user_busy_title">Kullanıcı meşgul</string>
<string name="audio_call_with_participant">%s ile sesli arama</string>
<string name="video_call_with_participant">%s ile görüntülü arama</string>
<plurals name="missed_video_call">
<item quantity="one">Cevapsız görüntülü arama</item>
<item quantity="other">%d cevapsız görüntülü aramalar</item>
</plurals>
<plurals name="missed_audio_call">
<item quantity="one">Cevapsız sesli arama</item>
<item quantity="other">%d cevapsız sesli aramalar</item>
</plurals>
<string name="call_ringing">Çağrı çalıyor…</string>
<string name="error_unauthorized">Yetkisiz, eksik geçerli kimlik doğrulama kimlik bilgileri</string>
<string name="login_error_homeserver_from_url_not_found_enter_manual">Ana sunucuyu seçin</string>
<string name="login_error_homeserver_from_url_not_found">%s url\'sinde bir ana sunucuya ulaşılamıyor. Lütfen bağlantınızı kontrol edin veya bir ana sunucuyu manuel olarak seçin.</string>
<string name="use_as_default_and_do_not_ask_again">Varsayılan olarak kullan ve tekrar sorma</string>
<string name="option_always_ask">Her zaman sor</string>
<string name="hs_client_url">Ana sunucu API URL\'si</string>
<string name="spaces_header">Alanlar</string>
<string name="spaces_invited_header">Davetliler</string>
<string name="settings_room_directory_show_all_rooms_summary">ık içeriğe sahip odalar da dahil olmak üzere oda dizinindeki tüm odaları göster.</string>
<string name="settings_room_directory_show_all_rooms">ık içerikli odaları göster</string>
<string name="settings_category_room_directory">Oda rehberi</string>
<string name="suggested_header">Önerilen Odalar</string>
<string name="dialog_edit_hint">Yeni değer</string>
<string name="action_not_now">Şimdi değil</string>
<string name="action_enable">Etkinleştirmek</string>
<string name="action_return">Geri dönüş</string>
<string name="action_switch">Değiştirmek</string>
<string name="missing_permissions_title">Eksik izinler</string>
<string name="denied_permission_voice_message">Sesli mesaj göndermek için lütfen Mikrofona izin verin.</string>
<string name="denied_permission_camera">Bu işlemi gerçekleştirmek için lütfen Kameraya sistem ayarlarından izin verin.</string>
<string name="denied_permission_generic">Bazı izinler eksik, bu eylemi gerçekleştirmek için lütfen sistem ayarlarından izinleri verin.</string>
<string name="spaces">Alanlar</string>
<string name="learn_more">daha fazla bilgi edin</string>
<string name="notification_listening_for_notifications">Bildirimleri dinleme</string>
<string name="notice_end_to_end_unknown_algorithm_by_you">Uçtan uca şifrelemeyi etkinleştirdiniz (tanınmayan algoritma %1$s).</string>
<string name="notice_end_to_end_unknown_algorithm">%1$s uçtan uca şifrelemeyi etkinleştirdi (tanınmayan algoritma %2$s).</string>
<string name="notice_end_to_end_ok_by_you">Uçtan uca şifrelemeyi açtın.</string>
<string name="notice_end_to_end_ok">%1$s uçtan uca şifrelemeyi etkinleştirdi.</string>
<string name="notice_direct_room_guest_access_forbidden_by_you">Konukların odaya katılmasını engellediniz.</string>
<string name="notice_direct_room_guest_access_forbidden">%1$s konukların odaya katılmasını engelledi.</string>
<string name="notice_room_guest_access_forbidden_by_you">Konukların odaya katılmasını engellediniz.</string>
<string name="notice_room_guest_access_forbidden">%1$s konukların odaya katılmasını engelledi.</string>
<string name="notice_direct_room_guest_access_can_join_by_you">Konukların buraya katılmasına izin verdiniz.</string>
<string name="notice_direct_room_guest_access_can_join">%1$s konukların buraya katılmasına izin verdi.</string>
<string name="notice_room_guest_access_can_join_by_you">Konukların odaya katılmasına izin verdiniz.</string>
<string name="notice_room_guest_access_can_join">%1$s konukların odaya katılmasına izin verdi.</string>
<string name="notice_room_canonical_alias_no_change_by_you">Bu odanın adreslerini değiştirdin.</string>
<string name="notice_room_canonical_alias_no_change">%1$s bu odanın adreslerini değiştirdi.</string>
<string name="notice_room_canonical_alias_main_and_alternative_changed_by_you">Bu odanın ana ve alternatif adreslerini değiştirdiniz.</string>
<string name="notice_room_canonical_alias_main_and_alternative_changed">%1$s bu odanın ana ve alternatif adreslerini değiştirdi.</string>
<string name="notice_room_canonical_alias_alternative_changed_by_you">Bu odanın alternatif adreslerini değiştirdiniz.</string>
<string name="notice_room_canonical_alias_alternative_changed">%1$s bu odanın alternatif adreslerini değiştirdi.</string>
<plurals name="notice_room_canonical_alias_alternative_removed_by_you">
<item quantity="one">Bu oda için %1$s alternatif adresini kaldırdınız.</item>
<item quantity="other">Bu oda için %1$s alternatif adreslerini kaldırdınız.</item>
</plurals>
<plurals name="notice_room_canonical_alias_alternative_removed">
<item quantity="one">%1$s bu oda için %2$s alternatif adresini kaldırdı.</item>
<item quantity="other">%1$s bu oda için %2$s alternatif adreslerini kaldırdı.</item>
</plurals>
<plurals name="notice_room_canonical_alias_alternative_added_by_you">
<item quantity="one">Bu oda için %1$s alternatif adresini eklediniz.</item>
<item quantity="other">Bu oda için %1$s alternatif adreslerini eklediniz.</item>
</plurals>
<plurals name="notice_room_canonical_alias_alternative_added">
<item quantity="one">%1$s, bu oda için %2$s alternatif adresini ekledi.</item>
<item quantity="other">%1$s, bu oda için %2$s alternatif adreslerini ekledi.</item>
</plurals>
<string name="notice_room_canonical_alias_unset_by_you">Bu odanın ana adresini kaldırdınız.</string>
<string name="notice_room_canonical_alias_unset">%1$s bu odanın ana adresini kaldırdı.</string>
<string name="notice_room_canonical_alias_set_by_you">Bu odanın ana adresini %1$s olarak ayarladınız.</string>
<string name="notice_room_canonical_alias_set">%1$s, bu odanın ana adresini %2$s olarak belirledi.</string>
<string name="notice_room_aliases_added_and_removed_by_you">Bu oda için adres olarak %1$s eklediniz ve %2$s\'i kaldırdınız.</string>
<string name="notice_room_aliases_added_and_removed">%1$s, bu oda için adres olarak %2$s ekledi ve %3$s\'i kaldırdı.</string>
<plurals name="notice_room_aliases_removed_by_you">
<item quantity="one">%1$s adresini bu odanın adresi olarak kaldırdınız.</item>
<item quantity="other">%1$s adresini bu oda için adres olarak kaldırdınız.</item>
</plurals>
<plurals name="notice_room_aliases_removed">
<item quantity="one">%1$s, %2$s adresini bu odanın adresi olarak kaldırdı.</item>
<item quantity="other">%1$s, %2$s adresini bu odanın adresi olarak kaldırdı.</item>
</plurals>
<plurals name="notice_room_aliases_added_by_you">
<item quantity="one">Bu oda için adres olarak %1$s eklediniz.</item>
<item quantity="other">Bu oda için adres olarak %1$s eklediniz.</item>
</plurals>
<plurals name="notice_room_aliases_added">
<item quantity="one">%1$s, bu oda için bir adres olarak %2$s ekledi.</item>
<item quantity="other">%1$s, bu oda için adres olarak %2$s ekledi.</item>
</plurals>
<string name="notice_room_withdraw_with_reason_by_you">%1$s adlı kişinin davetini geri çektiniz. Neden: %2$s</string>
<string name="notice_room_withdraw_with_reason">%1$s, %2$s adlı kişinin davetini geri çekti. Neden: %3$s</string>
<string name="notice_room_third_party_registered_invite_with_reason_by_you">%1$s davetini kabul ettiniz. Neden: %2$s</string>
<string name="notice_room_third_party_registered_invite_with_reason">%1$s, %2$s davetini kabul etti. Neden: %3$s</string>
<string name="notice_room_third_party_revoked_invite_with_reason_by_you">%1$s için odaya katılma davetini iptal ettiniz. Neden: %2$s</string>
<string name="notice_room_third_party_revoked_invite_with_reason">%1$s, %2$s için odaya katılma davetini iptal etti. Neden: %3$s</string>
<string name="notice_room_third_party_invite_with_reason_by_you">Odaya katılması için %1$s\'a bir davetiye gönderdiniz. Neden: %2$s</string>
<string name="notice_room_third_party_invite_with_reason">%1$s, odaya katılması için %2$s\'a bir davetiye gönderdi. Neden: %3$s</string>
<string name="notice_room_ban_with_reason_by_you">%1$s\'i yasakladınız. Neden: %2$s</string>
<string name="notice_room_ban_with_reason">%1$s, %2$s\'yi yasakladı. Neden: %3$s</string>
<string name="notice_room_unban_with_reason_by_you">%1$s yasağını kaldırdınız. Neden: %2$s</string>
<string name="notice_room_unban_with_reason">%1$s planlanmamış %2$s. Nedeni: %3$s</string>
<string name="notice_room_remove_with_reason_by_you">%1$s kaldırdınız. Nedeni: %2$s</string>
<string name="notice_room_remove_with_reason">%1$s %2$s kaldırıldı. Nedeni: %3$s</string>
<string name="notice_room_reject_with_reason_by_you">Daveti reddettiniz. Sebep: %1$s</string>
<string name="notice_room_reject_with_reason">%1$s daveti reddetti. Neden: %2$s</string>
<string name="notice_direct_room_leave_with_reason_by_you">Gittin. Sebep: %1$s</string>
<string name="notice_direct_room_leave_with_reason">%1$s kaldı. Neden: %2$s</string>
<string name="notice_room_leave_with_reason_by_you">Odadan ayrıldın. Sebep: %1$s</string>
<string name="notice_room_leave_with_reason">%1$s odadan ayrıldı. Neden: %2$s</string>
<string name="notice_direct_room_join_with_reason_by_you">Katıldın. Sebep: %1$s</string>
<string name="notice_direct_room_join_with_reason">%1$s katıldı. Neden: %2$s</string>
<string name="notice_room_join_with_reason_by_you">Odaya katıldın. Sebep: %1$s</string>
<string name="notice_room_join_with_reason">%1$s odaya katıldı. Neden: %2$s</string>
<string name="notice_room_invite_you_with_reason">%1$s sizi davet etti. Neden: %2$s</string>
<string name="notice_room_invite_with_reason_by_you">%1$s davet ettiniz. Neden: %2$s</string>
<string name="notice_room_invite_with_reason">%1$s, %2$s\'i davet etti. Neden: %3$s</string>
<string name="notice_room_invite_no_invitee_with_reason_by_you">Senin davetiyen. Sebep: %1$s</string>
<string name="notice_room_invite_no_invitee_with_reason">%1$s\'in davetiyesi. Neden: %2$s</string>
<string name="clear_timeline_send_queue">Gönderme kuyruğunu temizle</string>
<string name="event_status_sent_message">Mesajı gönderildi</string>
<string name="initial_sync_start_importing_account_data">İlk senkronizasyon:
\nHesap verilerini içe aktarma</string>
<string name="initial_sync_start_importing_account_groups">İlk senkronizasyon:
\nToplulukları içe aktarma</string>
<string name="initial_sync_start_importing_account_left_rooms">İlk senkronizasyon:
\nSol odalar içe aktarılıyor</string>
<string name="initial_sync_start_importing_account_invited_rooms">İlk senkronizasyon:
\nDavetli odaları içe aktarma</string>
<string name="initial_sync_start_importing_account_joined_rooms">İlk senkronizasyon:
\nKonuşmalarınız yükleniyor
\nÇok sayıda odaya katıldıysanız, bu biraz zaman alabilir</string>
<string name="initial_sync_start_importing_account_rooms">İlk senkronizasyon:
\nOdaları içe aktarma</string>
<string name="initial_sync_start_importing_account_crypto">İlk senkronizasyon:
\nKripto içe aktarma</string>
<string name="initial_sync_start_importing_account">İlk senkronizasyon:
\nHesap içe aktarılıyor…</string>
<string name="initial_sync_start_downloading">İlk senkronizasyon:
\nVeriler indiriliyor…</string>
<string name="initial_sync_start_server_computing">İlk senkronizasyon:
\nSunucu yanıtı bekleniyor…</string>
<string name="room_displayname_empty_room_was">Boş oda (%s idi)</string>
<plurals name="room_displayname_three_and_more_members">
<item quantity="one">%1$s ve 1 kişi daha</item>
<item quantity="other">%1$s ve %2$d kişi daha</item>
</plurals>
<plurals name="room_displayname_four_and_more_members">
<item quantity="one">%1$s, %2$s, %3$s ve %4$d diğer</item>
<item quantity="other">%1$s, %2$s, %3$s ve %4$d kişi daha</item>
</plurals>
<string name="room_displayname_4_members">%1$s, %2$s, %3$s ve %4$s</string>
<string name="room_displayname_two_members">%1$s ve %2$s</string>
<string name="room_displayname_invite_from">%s\'den davet</string>
<string name="room_error_access_unauthorized">Bu odaya katılmanıza izin verilmiyor</string>
<string name="room_error_join_failed_empty_room">Şu anda boş bir odaya yeniden katılmak mümkün değildir.</string>
<string name="could_not_redact">redaksiyon yapılamadı</string>
<string name="notice_crypto_error_unknown_inbound_session_id">Gönderenin cihazı bize bu mesajın anahtarlarını göndermedi.</string>
<string name="notice_crypto_unable_to_decrypt">** Şifre çözülemiyor: %s **</string>
<string name="notice_power_level_diff">%1$s, %2$s ile %3$s arasında</string>
<string name="notice_power_level_changed">%1$s, %2$s\'nin güç seviyesini değiştirdi.</string>
<string name="notice_power_level_changed_by_you">%1$s\'nin güç seviyesini değiştirdiniz.</string>
<string name="power_level_custom">Özel (%1$d)</string>
<string name="power_level_moderator">Moderatör</string>
<string name="power_level_admin">Admin</string>
<string name="notice_widget_jitsi_added">%1$s tarafından video konferans başlatıldı</string>
<string name="notice_widget_modified_by_you">%1$s widget\'ını değiştirdiniz</string>
<string name="notice_widget_added">%1$s, %2$s widget\'ı ekledi</string>
<string name="notice_profile_change_redacted">%1$s, %2$s profilini güncelledi</string>
<string name="notice_voip_finished">VoIP konferansı bitti</string>
<string name="notice_voip_started">VoIP konferansı başladı</string>
<string name="notice_requested_voip_conference_by_you">Bir VoIP konferansı talep ettiniz</string>
<string name="notice_requested_voip_conference">%1$s bir VoIP konferansı istedi</string>
<string name="notice_room_server_acl_allow_is_empty">🎉 Tüm sunucuların katılımı yasaklanmıştır! Bu oda artık kullanılamaz.</string>
<string name="notice_room_server_acl_updated_ip_literals_not_allowed">• IP değişmezleriyle eşleşen sunucular artık yasaklanmıştır.</string>
<string name="notice_room_server_acl_updated_ip_literals_allowed">• IP değişmez değerleriyle eşleşen sunuculara artık izin verilmektedir.</string>
<string name="notice_room_server_acl_updated_was_allowed">• %s ile eşleşen sunucular izin verilenler listesinden kaldırıldı.</string>
<string name="notice_room_server_acl_updated_allowed">• %s ile eşleşen sunuculara artık izin veriliyor.</string>
<string name="notice_room_server_acl_updated_was_banned">• %s ile eşleşen sunucular yasak listesinden kaldırıldı.</string>
<string name="notice_room_server_acl_updated_banned">• %s ile eşleşen sunucular artık yasaklandı.</string>
<string name="notice_room_server_acl_updated_title_by_you">Bu oda için sunucu ACL\'lerini değiştirdiniz.</string>
<string name="notice_room_server_acl_updated_title">%s, bu oda için sunucu ACL\'lerini değiştirdi.</string>
</resources> </resources>

View file

@ -3105,7 +3105,7 @@
<string name="delete_poll_dialog_content">Точно видалити опитування\? Ви не зможете відновити опитування після видалення.</string> <string name="delete_poll_dialog_content">Точно видалити опитування\? Ви не зможете відновити опитування після видалення.</string>
<string name="delete_poll_dialog_title">Видалити опитування</string> <string name="delete_poll_dialog_title">Видалити опитування</string>
<string name="poll_end_room_list_preview">Голосування завершене</string> <string name="poll_end_room_list_preview">Голосування завершене</string>
<string name="poll_response_room_list_preview">Голос надіслано</string> <string name="poll_response_room_list_preview">Проголосовано</string>
<string name="end_poll_confirmation_approve_button">Завершити опитування</string> <string name="end_poll_confirmation_approve_button">Завершити опитування</string>
<string name="end_poll_confirmation_description">Люди більше не зможуть голосувати, і будуть показані остаточні результати опитування.</string> <string name="end_poll_confirmation_description">Люди більше не зможуть голосувати, і будуть показані остаточні результати опитування.</string>
<string name="end_poll_confirmation_title">Завершити це опитування\?</string> <string name="end_poll_confirmation_title">Завершити це опитування\?</string>
@ -3163,7 +3163,40 @@
<string name="room_member_override_nick_color">Замінити колір псевдоніма</string> <string name="room_member_override_nick_color">Замінити колір псевдоніма</string>
<string name="login_splash_already_have_account">Я вже маю обліковий запис</string> <string name="login_splash_already_have_account">Я вже маю обліковий запис</string>
<string name="ftue_auth_carousel_4_title">Удоскональте спілкування в команді.</string> <string name="ftue_auth_carousel_4_title">Удоскональте спілкування в команді.</string>
<string name="ftue_auth_carousel_3_title">З\'єднуйтеся з будь-ким.</string> <string name="ftue_auth_carousel_3_title">Захищене спілкування.</string>
<string name="ftue_auth_carousel_2_title">Ви контролюєте все.</string> <string name="ftue_auth_carousel_2_title">Ви контролюєте все.</string>
<string name="ftue_auth_carousel_1_title">Володійте своїми розмовами.</string> <string name="ftue_auth_carousel_1_title">Володійте своїми розмовами.</string>
<string name="tooltip_attachment_location">Поділитися місцеперебуванням</string>
<string name="labs_render_locations_in_timeline">Зображувати місцеперебування користувача у стрічці</string>
<string name="settings_enable_location_sharing_summary">Після увімкнення ви зможете надіслати своє місцеперебування до будь-якої кімнати</string>
<string name="settings_enable_location_sharing">Увімкнути надсилання місцеперебування</string>
<string name="location_share_external">Відкрити за допомогою</string>
<string name="template_location_not_available_dialog_content">${app_name} не може отримати доступ до вашого місцеперебування. Спробуйте пізніше.</string>
<string name="template_location_not_available_dialog_title">${app_name} не може отримати доступ до вашого місцеперебування</string>
<string name="location_share">Поділитися місцеперебуванням</string>
<string name="a11y_location_share_icon">Поділитися місцеперебуванням</string>
<string name="location_activity_title_preview">Місцеперебування</string>
<string name="location_activity_title_static_sharing">Поділитися місцеперебуванням</string>
<string name="closed_poll_option_description">Результати можна переглянути лише після завершення опитування</string>
<string name="closed_poll_option_title">Закрите опитування</string>
<string name="open_poll_option_description">Усі, хто проголосує, побачать результати одразу після голосування</string>
<string name="open_poll_option_title">Відкрити опитування</string>
<string name="poll_type_title">Тип опитування</string>
<string name="edit_poll_button">РЕДАГУВАТИ ОПИТУВАННЯ</string>
<string name="edit_poll_title">Редагувати опитування</string>
<string name="poll_no_votes_cast">Немає голосових бесід</string>
<string name="a11y_trust_level_misconfigured">Неправильне налаштування рівня довіри</string>
<string name="encryption_misconfigured">Шифрування неправильно налаштовано</string>
<string name="room_profile_section_restore_security">Відновити шифрування</string>
<string name="contact_admin_to_restore_encryption">Зв\'яжіться з адміністратором для відновлення роботи шифрування.</string>
<string name="encryption_has_been_misconfigured">Шифрування неправильно налаштовано.</string>
<string name="sent_location">Поділилися своїм місцеперебуванням</string>
<string name="login_splash_create_account">Створити обліковий запис</string>
<string name="ftue_auth_carousel_title_messaging">Спілкування вашої команди.</string>
<string name="ftue_auth_carousel_body_encrypted">З наскрізним шифруванням і без вимоги номера телефону. Без реклами чи аналізу даних.</string>
<string name="ftue_auth_carousel_body_control">Оберіть де спілкуватись, що дасть вам контроль і незалежність. Під\'єднано через Matrix.</string>
<string name="ftue_auth_carousel_body_secure">Захищене та незалежне спілкування, яке дає вам такий самий рівень приватності, як розмова віч-на-віч у вашому власному домі.</string>
<string name="attachment_type_location">Місцеперебування</string>
<string name="room_unsupported_e2e_algorithm_as_admin">Шифрування було налаштовано неправильно, тому ви не можете надсилати повідомлення. Торкніться, щоб відкрити налаштування.</string>
<string name="room_unsupported_e2e_algorithm">Шифрування було налаштовано неправильно, тому ви не можете надсилати повідомлення. Зверніться до адміністратора, щоб відновити роботу шифрування.</string>
</resources> </resources>

View file

@ -542,7 +542,7 @@
<string name="room_participants_action_mention">提及</string> <string name="room_participants_action_mention">提及</string>
<string name="room_participants_action_devices_list">顯示工作階段清單</string> <string name="room_participants_action_devices_list">顯示工作階段清單</string>
<string name="room_participants_invite_prompt_msg">您確定想要邀請 %s 到聊天室?</string> <string name="room_participants_invite_prompt_msg">您確定想要邀請 %s 到聊天室?</string>
<string name="room_participants_ban_prompt_msg">封鎖使用者將會把他們從此聊天室中除,並避免他們再次加入。</string> <string name="room_participants_ban_prompt_msg">封鎖使用者將會把他們從此聊天室中除,並避免他們再次加入。</string>
<string name="people_search_invite_by_id"><u>透過 ID 邀請</u></string> <string name="people_search_invite_by_id"><u>透過 ID 邀請</u></string>
<string name="people_search_local_contacts">裝置上的聯絡人(%d</string> <string name="people_search_local_contacts">裝置上的聯絡人(%d</string>
<string name="people_search_user_directory">使用者目錄 (%s)</string> <string name="people_search_user_directory">使用者目錄 (%s)</string>
@ -1046,7 +1046,7 @@
<string name="settings_show_read_receipts">顯示讀取回條</string> <string name="settings_show_read_receipts">顯示讀取回條</string>
<string name="settings_show_read_receipts_summary">點選讀取回條以顯示詳細資料。</string> <string name="settings_show_read_receipts_summary">點選讀取回條以顯示詳細資料。</string>
<string name="settings_show_join_leave_messages">顯示加入與離開的活動</string> <string name="settings_show_join_leave_messages">顯示加入與離開的活動</string>
<string name="settings_show_join_leave_messages_summary">邀請、踢出與封鎖不受影響。</string> <string name="settings_show_join_leave_messages_summary">邀請、移除與封鎖不受影響。</string>
<string name="settings_show_avatar_display_name_changes_messages">顯示帳號活動</string> <string name="settings_show_avatar_display_name_changes_messages">顯示帳號活動</string>
<string name="settings_show_avatar_display_name_changes_messages_summary">包含大頭貼與顯示名稱變動。</string> <string name="settings_show_avatar_display_name_changes_messages_summary">包含大頭貼與顯示名稱變動。</string>
<string name="settings_password">密碼</string> <string name="settings_password">密碼</string>
@ -2298,7 +2298,7 @@
<item quantity="other">%d 秒</item> <item quantity="other">%d 秒</item>
</plurals> </plurals>
<string name="settings_show_room_member_state_events">顯示聊天室成員狀態活動</string> <string name="settings_show_room_member_state_events">顯示聊天室成員狀態活動</string>
<string name="settings_show_room_member_state_events_summary">包含邀請/加入/離開/除/封鎖事件與大頭貼/顯示名稱變更等。</string> <string name="settings_show_room_member_state_events_summary">包含邀請/加入/離開/除/封鎖事件與大頭貼/顯示名稱變更等。</string>
<string name="sent_a_poll">投票</string> <string name="sent_a_poll">投票</string>
<string name="sent_a_reaction">反應:%s</string> <string name="sent_a_reaction">反應:%s</string>
<string name="sent_verification_conclusion">驗證結論</string> <string name="sent_verification_conclusion">驗證結論</string>
@ -2902,7 +2902,7 @@
<string name="space_settings_permissions_subtitle">檢視並更新變更空間各部份所需的角色。</string> <string name="space_settings_permissions_subtitle">檢視並更新變更空間各部份所需的角色。</string>
<string name="space_settings_permissions_title">空間權限</string> <string name="space_settings_permissions_title">空間權限</string>
<string name="space_participants_unban_prompt_msg">取消封鎖使用者將讓他們可以再次加入空間。</string> <string name="space_participants_unban_prompt_msg">取消封鎖使用者將讓他們可以再次加入空間。</string>
<string name="space_participants_ban_prompt_msg">封鎖使用者會將他們踢出此空間並防止他們再次加入。</string> <string name="space_participants_ban_prompt_msg">封鎖使用者會將他們自此空間移除並防止他們再次加入。</string>
<string name="space_participants_remove_prompt_msg">踢除使用者將會將他們從此空間中移除。 <string name="space_participants_remove_prompt_msg">踢除使用者將會將他們從此空間中移除。
\n \n
\n為了防止他們再加入您應該封鎖他們。</string> \n為了防止他們再加入您應該封鎖他們。</string>
@ -3002,7 +3002,40 @@
<string name="room_member_override_nick_color">覆寫暱稱色彩</string> <string name="room_member_override_nick_color">覆寫暱稱色彩</string>
<string name="login_splash_already_have_account">我已有一個帳號</string> <string name="login_splash_already_have_account">我已有一個帳號</string>
<string name="ftue_auth_carousel_4_title">減少團隊的懈怠。</string> <string name="ftue_auth_carousel_4_title">減少團隊的懈怠。</string>
<string name="ftue_auth_carousel_3_title">與任何人聯絡</string> <string name="ftue_auth_carousel_3_title">安全傳送訊息</string>
<string name="ftue_auth_carousel_2_title">您已掌控了您的資料。</string> <string name="ftue_auth_carousel_2_title">您已掌控了您的資料。</string>
<string name="ftue_auth_carousel_1_title">擁有您的對話。</string> <string name="ftue_auth_carousel_1_title">擁有您的對話。</string>
<string name="tooltip_attachment_location">分享位置</string>
<string name="labs_render_locations_in_timeline">在時間軸中繪製使用者位置</string>
<string name="settings_enable_location_sharing_summary">啟用後,您就能將您的位置傳送至任何聊天室</string>
<string name="settings_enable_location_sharing">啟用位置分享</string>
<string name="location_share_external">開啟以</string>
<string name="template_location_not_available_dialog_content">${app_name} 無法存取您的位置。請稍後再試。</string>
<string name="template_location_not_available_dialog_title">${app_name} 無法存取您的位置</string>
<string name="location_share">分享位置</string>
<string name="a11y_location_share_icon">分享位置</string>
<string name="location_activity_title_preview">位置</string>
<string name="location_activity_title_static_sharing">分享位置</string>
<string name="closed_poll_option_description">結果僅在您結束投票後顯示</string>
<string name="closed_poll_option_title">已關閉投票</string>
<string name="open_poll_option_description">投票者在投票後可以立刻看到投票結果</string>
<string name="open_poll_option_title">開啟投票</string>
<string name="poll_type_title">投票類型</string>
<string name="edit_poll_button">編輯投票</string>
<string name="edit_poll_title">編輯投票</string>
<string name="poll_no_votes_cast">沒有投票</string>
<string name="a11y_trust_level_misconfigured">信任層級設定錯誤</string>
<string name="encryption_misconfigured">加密設定錯誤</string>
<string name="room_profile_section_restore_security">還原加密</string>
<string name="contact_admin_to_restore_encryption">請聯絡管理員以將加密還原至有效狀態。</string>
<string name="encryption_has_been_misconfigured">加密設定錯誤。</string>
<string name="sent_location">分享了他們的位置</string>
<string name="login_splash_create_account">建立帳號</string>
<string name="ftue_auth_carousel_title_messaging">為您的團隊傳送訊息。</string>
<string name="ftue_auth_carousel_body_encrypted">端到端加密,不需要電話號碼。沒有廣告或資料挖礦。</string>
<string name="ftue_auth_carousel_body_control">選擇保留對話的位置,讓您擁有控制權與獨立性。透過 Matrix 連結。</string>
<string name="ftue_auth_carousel_body_secure">安全且獨立的通訊,為您提供與在家中進行面對面對話相同的隱私等級。</string>
<string name="attachment_type_location">位置</string>
<string name="room_unsupported_e2e_algorithm_as_admin">加密設定錯誤,因此您無法傳送訊息。點擊以開啟設定。</string>
<string name="room_unsupported_e2e_algorithm">加密設定錯誤,因此您無法傳送訊息。請聯絡管理員將加密還原至有效的狀態。</string>
</resources> </resources>

View file

@ -3737,6 +3737,7 @@
<string name="location_activity_title_static_sharing">Share location</string> <string name="location_activity_title_static_sharing">Share location</string>
<string name="location_activity_title_preview">Location</string> <string name="location_activity_title_preview">Location</string>
<string name="a11y_location_share_icon">Share location</string> <string name="a11y_location_share_icon">Share location</string>
<string name="a11y_static_map_image">Map</string>
<string name="location_share">Share location</string> <string name="location_share">Share location</string>
<string name="template_location_not_available_dialog_title">${app_name} could not access your location</string> <string name="template_location_not_available_dialog_title">${app_name} could not access your location</string>
<string name="template_location_not_available_dialog_content">${app_name} could not access your location. Please try again later.</string> <string name="template_location_not_available_dialog_content">${app_name} could not access your location. Please try again later.</string>

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.location
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeNull
import org.junit.Test
class LocationDataTest {
@Test
fun validCases() {
parseGeo("geo:12.34,56.78;13.56") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = 13.56)
parseGeo("geo:12.34,56.78") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = null)
// Error is ignored in case of invalid uncertainty
parseGeo("geo:12.34,56.78;13.5z6") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = null)
parseGeo("geo:12.34,56.78;13. 56") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = null)
// Space are ignored (trim)
parseGeo("geo: 12.34,56.78;13.56") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = 13.56)
parseGeo("geo:12.34,56.78; 13.56") shouldBeEqualTo
LocationData(latitude = 12.34, longitude = 56.78, uncertainty = 13.56)
}
@Test
fun invalidCases() {
parseGeo("").shouldBeNull()
parseGeo("geo").shouldBeNull()
parseGeo("geo:").shouldBeNull()
parseGeo("geo:12.34").shouldBeNull()
parseGeo("geo:12.34;13.56").shouldBeNull()
parseGeo("gea:12.34,56.78;13.56").shouldBeNull()
parseGeo("geo:12.x34,56.78;13.56").shouldBeNull()
parseGeo("geo:12.34,56.7y8;13.56").shouldBeNull()
// Spaces are not ignored if inside the numbers
parseGeo("geo:12.3 4,56.78;13.56").shouldBeNull()
parseGeo("geo:12.34,56.7 8;13.56").shouldBeNull()
// Or in the protocol part
parseGeo(" geo:12.34,56.78;13.56").shouldBeNull()
parseGeo("ge o:12.34,56.78;13.56").shouldBeNull()
parseGeo("geo :12.34,56.78;13.56").shouldBeNull()
}
}