diff --git a/CHANGES.md b/CHANGES.md index 579124ce45..3aefa2b2ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,15 @@ -Changes in Element 1.0.14 (2020-XX-XX) +Changes in Element 1.0.15 (2020-XX-XX) =================================================== Features ✨: - Allow changing nick colors (#2610) - - Enable url previews for notices (#2562) + - Improvements 🙌: - Bugfix 🐛: - - Url previews sometimes attached to wrong message (#2561) + - Translations 🗣: - @@ -23,6 +23,40 @@ Build 🧱: Test: - +Other changes: + - Update Dagger to 2.31 version so we can use the embedded AssistedInject feature + +Changes in Element 1.0.14 (2020-01-15) +=================================================== + +Features ✨: + - Enable url previews for notices (#2562) + - Edit room permissions (#2471) + +Improvements 🙌: + - Add System theme option and set as default (#904, #2387) + - Store megolm outbound session to improve send time of first message after app launch. + - Warn user when they are leaving a not public room (#1460) + - Option to disable emoji keyboard (#2563) + +Bugfix 🐛: + - Unspecced msgType field in m.sticker (#2580) + - Wait for all room members to be known before sending a message to a e2e room (#2518) + - Url previews sometimes attached to wrong message (#2561) + - Room Topic not displayed correctly after visiting a link (#2551) + - Hiding membership events works the exact opposite (#2603) + - Tapping drawer having more than 1 room in notifications gives "malformed link" error (#2605) + - Sent image not displayed when opened immediately after sending (#409) + - Initial sync is not retried correctly when there is some network error. (#2632) + - Fix switch theme issue, and white field issue (#2599, #2528) + - Fix request too large Uri error when joining a room + +Translations 🗣: + - New language supported: Hebrew + +Build 🧱: + - Remove dependency to org.greenrobot.eventbus library + Other changes: - Migrate to ViewBindings (#1072) diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt index ae095be41a..9b1345cd39 100644 --- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt +++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt @@ -40,13 +40,16 @@ import kotlin.math.abs abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventListener { - lateinit var pager2: ViewPager2 - lateinit var imageTransitionView: ImageView - lateinit var transitionImageContainer: ViewGroup + protected val pager2: ViewPager2 + get() = views.attachmentPager + protected val imageTransitionView: ImageView + get() = views.transitionImageView + protected val transitionImageContainer: ViewGroup + get() = views.transitionImageContainer - var topInset = 0 - var bottomInset = 0 - var systemUiVisibility = true + private var topInset = 0 + private var bottomInset = 0 + private var systemUiVisibility = true private var overlayView: View? = null set(value) { @@ -65,14 +68,16 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi private lateinit var gestureDetector: GestureDetectorCompat var currentPosition = 0 + private set private var swipeDirection: SwipeDirection? = null private fun isScaled() = attachmentsAdapter.isScaled(currentPosition) + private val attachmentsAdapter = AttachmentsAdapter() + private var wasScaled: Boolean = false private var isSwipeToDismissAllowed: Boolean = true - private lateinit var attachmentsAdapter: AttachmentsAdapter private var isOverlayWasClicked = false // private val shouldDismissToBottom: Boolean @@ -101,10 +106,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi views = ActivityAttachmentViewerBinding.inflate(layoutInflater) setContentView(views.root) views.attachmentPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL - attachmentsAdapter = AttachmentsAdapter() views.attachmentPager.adapter = attachmentsAdapter - imageTransitionView = views.transitionImageView - pager2 = views.attachmentPager directionDetector = createSwipeDirectionDetector() gestureDetector = createGestureDetector() diff --git a/docs/ui-tests.md b/docs/ui-tests.md index ff01da0b31..6ebb52abe8 100644 --- a/docs/ui-tests.md +++ b/docs/ui-tests.md @@ -27,7 +27,6 @@ $ source env/bin/activate Every time you want to launch these test homeservers, type: ```shell script -$ virtualenv -p python3 env $ source env/bin/activate (env) $ demo/start.sh --no-rate-limit ``` diff --git a/fastlane/metadata/android/de/changelogs/40100100.txt b/fastlane/metadata/android/de/changelogs/40100100.txt index 70b786d12e..2faf4b5d39 100644 --- a/fastlane/metadata/android/de/changelogs/40100100.txt +++ b/fastlane/metadata/android/de/changelogs/40100100.txt @@ -1 +1,2 @@ -// TODO +Diese neue Version enthält hauptsächlich Fehlerkorrekturen und Verbesserungen. Nachrichten verschicken geht jetzt viel schneller. +Vollständige Versionshinweise: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/de/changelogs/40100110.txt b/fastlane/metadata/android/de/changelogs/40100110.txt new file mode 100644 index 0000000000..e70007b5d7 --- /dev/null +++ b/fastlane/metadata/android/de/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Diese neue Version enthält hauptsächlich Verbesserungen der Benutzer*innenoberfläche und der Handhabung. Du kannst jetzt ganz schnell Freund*innen einladen und DMs erstellen, indem du schlicht einen QR-Code scannst. +Vollständige Versionshinweise: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/en-US/changelogs/40100130.txt b/fastlane/metadata/android/en-US/changelogs/40100130.txt index 39715c2910..dc517fac48 100644 --- a/fastlane/metadata/android/en-US/changelogs/40100130.txt +++ b/fastlane/metadata/android/en-US/changelogs/40100130.txt @@ -1,2 +1,2 @@ Main changes in this version: URL Preview, new Emoji keyboard, new room settings capabilities, and snow for Christmas! -Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.12 \ No newline at end of file +Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.13 \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/40100140.txt b/fastlane/metadata/android/en-US/changelogs/40100140.txt new file mode 100644 index 0000000000..74f609fa15 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40100140.txt @@ -0,0 +1,2 @@ +Main changes in this version: Edit room permissions, automatic light/dark theme, and a bunch of bug fixes. +Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.14 \ No newline at end of file diff --git a/fastlane/metadata/android/et/changelogs/40100100.txt b/fastlane/metadata/android/et/changelogs/40100100.txt new file mode 100644 index 0000000000..11a040ceb0 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Selles uues versioonis leidub põhiliselt veaparandusi ja pisikohendusi. Sõnumite saatmine on nüüd märkatavalt kiirem. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/et/changelogs/40100110.txt b/fastlane/metadata/android/et/changelogs/40100110.txt new file mode 100644 index 0000000000..019a84a2be --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Uues versioonis leidub põhiliselt kasutajaliidese ning kasutajakogemuse parandusi. Nüüd saad sõpradele kutseid saata ning otsevestlusi alustada QR-koodi lugemise abil. +Kõik muudatused: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/fa/changelogs/40100100.txt b/fastlane/metadata/android/fa/changelogs/40100100.txt index 6123bfc7fc..080d80a3ad 100644 --- a/fastlane/metadata/android/fa/changelogs/40100100.txt +++ b/fastlane/metadata/android/fa/changelogs/40100100.txt @@ -1 +1,2 @@ -// برای انجام +این نگارش جدید به طور عمده شامل رفع اشکال‌ها و بهبودها است. ارسال پیام اکنون بسیار سریعتر است. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/fa/changelogs/40100110.txt b/fastlane/metadata/android/fa/changelogs/40100110.txt new file mode 100644 index 0000000000..c95922e2d7 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40100110.txt @@ -0,0 +1,2 @@ +این نگارش جدید به طور عمده شامل رابط کاربری و بهبود تجربه کاربر است. اکنون می‌توانید با پویش کدهای QR دوستانتان را دعوت کرده و بسیار سریع پیام مستقیم ایجاد کنید. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/fa/short_description.txt b/fastlane/metadata/android/fa/short_description.txt index 4cfa767649..aba229f959 100644 --- a/fastlane/metadata/android/fa/short_description.txt +++ b/fastlane/metadata/android/fa/short_description.txt @@ -1 +1 @@ -گپ و تماس نامتمرکز امن. داده‌هایتان را از شرکت‌ها امن نگه دارید. +گپ و تماس نامتمرکز امن. داده‌هایتان را از اشخاص سوم امن نگه دارید. diff --git a/fastlane/metadata/android/fa/title.txt b/fastlane/metadata/android/fa/title.txt index fb4ea4125e..899b3d6adb 100644 --- a/fastlane/metadata/android/fa/title.txt +++ b/fastlane/metadata/android/fa/title.txt @@ -1 +1 @@ -المنت (ریوت سابق) +Element (پیشتر Riot.im) diff --git a/fastlane/metadata/android/fi/changelogs/40100110.txt b/fastlane/metadata/android/fi/changelogs/40100110.txt new file mode 100644 index 0000000000..356eabd29b --- /dev/null +++ b/fastlane/metadata/android/fi/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Tämä versio sisältää pääosin käyttöliittymä- ja käyttökokemusparannuksia. Voit nyt kutsua kavereita ja luoda yksityisviestejä nopeasti QR-koodeja lukemalla. +Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/fi/full_description.txt b/fastlane/metadata/android/fi/full_description.txt index 70def518da..947d19ce3d 100644 --- a/fastlane/metadata/android/fi/full_description.txt +++ b/fastlane/metadata/android/fi/full_description.txt @@ -1,30 +1,30 @@ Element on uudenlainen viestinsovellus, joka: -1. Antaa sinun päättää yksityisyydestäsi. +1. Antaa sinun päättää yksityisyydestäsi 2. Antaa sinun kommunikoida kenen tahansa kanssa Matrix-verkossa ja jopa sen ulkopuolella siltaamalla sovelluksiin, kuten Slack 3. Suojaa sinua mainonnalta, tietojen keräämiseltä ja suljetuilta alustoilta 4. Suojaa sinut päästä päähän -salauksella sekä ristiin varmentamisella muiden todentamiseksi Element eroaa täysin muista viestintäsovelluksista, koska se on hajautettu ja avointa lähdekoodia. -Element antaa sinun isännöidä itse - valita isännän - jotta sinulla on yksityisyys ja voit hallita tietojasi sekä keskustelujasi. Se antaa sinulle pääsyn avoimeen verkkoon; joten et ole jumissa Elementin käyttäjissä. +Element antaa sinun isännöidä itse - tai valita palveluntarjoajan - jotta sinulla on yksityisyys ja voit hallita tietojasi sekä keskustelujasi. Se antaa sinulle pääsyn avoimeen verkkoon, joten et jää juttelemaan vain toisten Elementin käyttäjien kanssa. Se on myös hyvin turvallinen. Element pystyy tekemään kaiken tämän, koska se toimii Matrixilla - avoimella, hajautetun viestinnän standardilla. -Element antaa sinulle hallinnan antamalla sinun valita, kuka isännöi keskustelujasi. Element-sovelluksessa voit valita isännän eri tavoin: +Element antaa sinulle päätösvallan antamalla sinun valita, kuka isännöi keskustelujasi. Element-sovelluksessa voit valita isännän eri tavoin: 1. Hanki ilmainen tili Matrix-kehittäjien ylläpitämällä matrix.org-palvelimella tai valitse tuhansista vapaaehtoisten ylläpitämistä julkisista palvelimista. -2. Isännöi tiliäsi itse suorittamalla palvelinta omalla laitteellasi -3. Luo tili mukautetulla palvelimella yksinkertaisesti tilaamalla Element Matrix Services -palvelu +2. Isännöi tiliäsi itse ylläpitämällä palvelinta omalla laitteellasi +3. Luo tili sinua varten tehdyllä palvelimella tilaamalla Element Matrix Services -palvelu Miksi valita Element? -OMAT TIEDOT: Sinä päätät, missä tietosi ja viestisi säilytetään. Hallitset sitä itse, eikä jokin MEGAYHTIÖ, joka tutkii tietojasi tai antaa niitä kolmansille osapuolille. +OMAT TIEDOT: Sinä päätät, missä tietosi ja viestisi säilytetään. Sinä määräät, ei jokin jättiyhtiö, joka tutkii tietojasi tai antaa niitä kolmansille osapuolille. -AVOIN KOMMUNIKOINYI JA YHTEISTYÖ: Voit keskustella kaikkien muiden Matrix-verkon käyttäjien kanssa, riippumatta siitä käyttävätkö he Elementiä tai muuta Matrix-sovellusta, ja vaikka he käyttäisivät eri viestijärjestelmiä, kuten Slack, IRC tai XMPP. +AVOINTA VIESTINTÄÄ JA YHTEISTYÖTÄ: Voit keskustella kaikkien muiden Matrix-verkon käyttäjien kanssa, riippumatta siitä käyttävätkö he Elementiä tai muuta Matrix-sovellusta, ja vaikka he käyttäisivät eri viestijärjestelmiä, kuten Slack, IRC tai XMPP. ERITTÄIN TURVALLINEN: Vahva päästä päähän -salaus (vain keskustelussa olevat voivat purkaa viestien salauksen), ja ristiin varmentaminen keskustelun osallistujien laitteiden tarkistamiseksi. -TÄYDELLISTÄ VIESTINTÄÄ: Viestit, ääni- ja videopuhelut, tiedostojen jakaminen, näytön jakaminen ja koko joukko integraatioita, botteja ja widgettejä. Rakenna huoneita, yhteisöjä, pidä yhteyttä ja tee asioita. +KATTAVAA VIESTINTÄÄ: Viestit, ääni- ja videopuhelut, tiedostojen jakaminen, näytön jakaminen ja koko joukko integraatioita, botteja ja sovelmia. Rakenna huoneita ja yhteisöjä, pidä yhteyttä ja hoida asiasi. MISSÄ TAHANSA OLETKIN: Pidä yhteyttä missä tahansa, täysin synkronoidun viestihistorian kautta kaikilla laitteillasi ja verkossa osoitteessa https://app.element.io. diff --git a/fastlane/metadata/android/fi/short_description.txt b/fastlane/metadata/android/fi/short_description.txt index 5573ac1cb9..64f35a7dff 100644 --- a/fastlane/metadata/android/fi/short_description.txt +++ b/fastlane/metadata/android/fi/short_description.txt @@ -1 +1 @@ -Turvallista, hajautettua, keskusteluja ja VoIP-puheluita. Pidä tietosi turvassa. +Turvallista, hajautettua keskustelua ja VoIP-puheluita. Pidä tietosi turvassa. diff --git a/fastlane/metadata/android/fr/changelogs/40100100.txt b/fastlane/metadata/android/fr/changelogs/40100100.txt new file mode 100644 index 0000000000..36ca3016b6 --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Cette nouvelle version contient principalement des corrections de bogues et des améliorations. Envoyer un message est maintenant plus rapide. +Liste complète des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/hu/changelogs/40100100.txt b/fastlane/metadata/android/hu/changelogs/40100100.txt new file mode 100644 index 0000000000..87a00efded --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Ez az új verzió főképp hibajavításokat, és teljesítménybeli fejlesztéseket tartalmaz. Most már sokkal gyorsabb az üzenetek elküldése. +A változtatások teljes listája itt található: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/hu/changelogs/40100110.txt b/fastlane/metadata/android/hu/changelogs/40100110.txt new file mode 100644 index 0000000000..c14ed73aeb --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Ez az új verzió főleg a felhasználói felülettel és a felhasználói élménnyel kapcsolatos javításokat tartalmaz. Mostantól már sokkal gyorsabban hívhatsz meg új ismerősöket a QR kód beolvasás által. +A változtatások teljes listája itt található: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/hu/full_description.txt b/fastlane/metadata/android/hu/full_description.txt index dfc842594d..b75f259d02 100644 --- a/fastlane/metadata/android/hu/full_description.txt +++ b/fastlane/metadata/android/hu/full_description.txt @@ -17,7 +17,7 @@ Az Element a te kezedbe adja az irányítást azáltal, hogy eldöntheted, ki t 2. A saját számítógépeden is futtathatsz szervert 3. Előfizethetsz egy saját szerverre az Element Matrix Szolgáltatások platformon -Miért válaszd az Element-et? +Miért jó az Element-et választani? ADATAID MEGVÉDÉSE: Eldöntheted, hol tárold az adataid és üzeneteid. A te tulajdonodban van, nem valami megacégnél, ami bányássza az adataid, vagy továbbadja másoknak. diff --git a/fastlane/metadata/android/it/changelogs/40100110.txt b/fastlane/metadata/android/it/changelogs/40100110.txt new file mode 100644 index 0000000000..897dda36d2 --- /dev/null +++ b/fastlane/metadata/android/it/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Questa nuova versione contiene principalmente miglioramenti di interfaccia ed esperienza utente. Ora puoi invitare amici e iniziare messaggi diretti rapidamente tramite codici QR. +Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/nb_NO/changelogs/40100100.txt b/fastlane/metadata/android/nb_NO/changelogs/40100100.txt new file mode 100644 index 0000000000..7ef80a2532 --- /dev/null +++ b/fastlane/metadata/android/nb_NO/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Denne nye versjonen inneholder hovedsakelig feilrettinger og forbedringer. Å sende en melding er nå mye raskere. +Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/nb_NO/changelogs/40100110.txt b/fastlane/metadata/android/nb_NO/changelogs/40100110.txt new file mode 100644 index 0000000000..c2f5e03845 --- /dev/null +++ b/fastlane/metadata/android/nb_NO/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Denne nye versjonen inneholder hovedsakelig forbedringer av brukergrensesnittet og brukeropplevelsen. Nå kan du invitere venner og opprette DM veldig raskt ved å skanne QR-koder. +Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/nb_NO/short_description.txt b/fastlane/metadata/android/nb_NO/short_description.txt new file mode 100644 index 0000000000..b7cad4c849 --- /dev/null +++ b/fastlane/metadata/android/nb_NO/short_description.txt @@ -0,0 +1 @@ +Sikker desentralisert chat & VoIP. Beskytt dataene dine fra tredjeparter. diff --git a/fastlane/metadata/android/nb_NO/title.txt b/fastlane/metadata/android/nb_NO/title.txt new file mode 100644 index 0000000000..aacee5be54 --- /dev/null +++ b/fastlane/metadata/android/nb_NO/title.txt @@ -0,0 +1 @@ +Element (tidligere Riot.im) diff --git a/fastlane/metadata/android/pt_BR/changelogs/40100110.txt b/fastlane/metadata/android/pt_BR/changelogs/40100110.txt new file mode 100644 index 0000000000..2e9aef1c4a --- /dev/null +++ b/fastlane/metadata/android/pt_BR/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Esta nova versão contém principalmente melhorias na interface do usuário e na experiência do usuário. Agora você pode convidar amigos e criar conversas rapidamente, digitalizando códigos QR. +Registro completo de alterações: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/ru/changelogs/40100100.txt b/fastlane/metadata/android/ru/changelogs/40100100.txt new file mode 100644 index 0000000000..326562fb32 --- /dev/null +++ b/fastlane/metadata/android/ru/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Эта новая версия в основном содержит исправления ошибок и улучшения. Отправка сообщения стала намного быстрее. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/ru/changelogs/40100110.txt b/fastlane/metadata/android/ru/changelogs/40100110.txt new file mode 100644 index 0000000000..166e5b701c --- /dev/null +++ b/fastlane/metadata/android/ru/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Эта новая версия в основном содержит улучшения пользовательского интерфейса и взаимодействия с пользователем. Теперь вы можете приглашать друзей и очень быстро создавать чаты, сканируя QR-коды. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/sk/changelogs/40100100.txt b/fastlane/metadata/android/sk/changelogs/40100100.txt new file mode 100644 index 0000000000..b5fe2085ca --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Táto verzia obsahuje predovšetkým opravy chýb. Odosielanie správ je odteraz omnoho rýchlejšie. +Kompletný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/sk/changelogs/40100110.txt b/fastlane/metadata/android/sk/changelogs/40100110.txt new file mode 100644 index 0000000000..ae68eee15e --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Táto verzia obsahuje najmä vylepšenia používateľského rozhrania. Pozývať priateľov alebo vytvárať priame konverzácie môžete veľmi rýchlo naskenovaním QR kódov. +Kompletný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/sv/changelogs/40100110.txt b/fastlane/metadata/android/sv/changelogs/40100110.txt new file mode 100644 index 0000000000..e3ed460f17 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Den här nya versionen innehåller mest förbättringar för användargränssnittet och användarupplevelsen. Du kan nu bjuda in vänner och skapa direktmeddelanden väldigt snabbt genom att skanna QR-koder. +Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/uk/changelogs/40100110.txt b/fastlane/metadata/android/uk/changelogs/40100110.txt new file mode 100644 index 0000000000..32f220e75d --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Ця нова версія містить переважно поліпшення інтерфейсу та зручності користування. Тепер ви можете запросити друзів і створити прямі повідомлення дуже швидко, скануючи QR-коди. +Повний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/vi/changelogs/40100100.txt b/fastlane/metadata/android/vi/changelogs/40100100.txt new file mode 100644 index 0000000000..7125bbde9a --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Phiên bản mới này chủ yếu bao gồm sửa lỗi và một số cải thiện. Gửi tin nhắn trở nên nhanh chóng hơn trước. +Danh sách đầy đủ các thay đổi: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/vi/changelogs/40100110.txt b/fastlane/metadata/android/vi/changelogs/40100110.txt new file mode 100644 index 0000000000..fce5eff648 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Phiên bản mới này chủ yếu bao gồm các cải thiện về giao diện và trải nghiệm người dùng. Bây giờ bạn có thể mời bạn bè và bắt đầu nói chuyện nhanh chóng bằng cách quét mã QR. +Danh sách đầy đủ các thay đổi: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/vi/short_description.txt b/fastlane/metadata/android/vi/short_description.txt new file mode 100644 index 0000000000..b41ac0ce82 --- /dev/null +++ b/fastlane/metadata/android/vi/short_description.txt @@ -0,0 +1 @@ +Ứng dụng chat và gọi phân tán bảo mật. Bảo vệ dữ liệu của bạn khỏi bên thứ ba. diff --git a/fastlane/metadata/android/vi/title.txt b/fastlane/metadata/android/vi/title.txt new file mode 100644 index 0000000000..2a3bef31df --- /dev/null +++ b/fastlane/metadata/android/vi/title.txt @@ -0,0 +1 @@ +Element (trước là Riot.im) diff --git a/fastlane/metadata/android/zh_Hant/changelogs/40100110.txt b/fastlane/metadata/android/zh_Hant/changelogs/40100110.txt new file mode 100644 index 0000000000..22dfe07097 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant/changelogs/40100110.txt @@ -0,0 +1,2 @@ +這個新版本主要包含使用者介面與使用者體驗改善。現在您可以邀請朋友,並透過掃描 QR code 來快速建立直接訊息了。 +完整變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/zh_Hant/changelogs/40100120.txt b/fastlane/metadata/android/zh_Hant/changelogs/40100120.txt new file mode 100644 index 0000000000..846126af63 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant/changelogs/40100120.txt @@ -0,0 +1,2 @@ +此版本中的主要變更:URL 預覽、新的表情符號鍵盤、新的聊天室設定功能以及聖誕節降雪! +完整變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.0.12 diff --git a/fastlane/metadata/android/zh_Hant/changelogs/40100130.txt b/fastlane/metadata/android/zh_Hant/changelogs/40100130.txt new file mode 100644 index 0000000000..846126af63 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant/changelogs/40100130.txt @@ -0,0 +1,2 @@ +此版本中的主要變更:URL 預覽、新的表情符號鍵盤、新的聊天室設定功能以及聖誕節降雪! +完整變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.0.12 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cdc95ef6eb..247e2b90ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ +#Fri Jan 15 11:30:47 CET 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionSha256Sum=a7ca23b3ccf265680f2bfd35f1f00b1424f4466292c7337c85d46c9641b3f053 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index d72e5bda41..7d5432ebb8 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -112,7 +112,7 @@ dependencies { def lifecycle_version = '2.2.0' def arch_version = '2.1.0' def markwon_version = '3.1.0' - def daggerVersion = '2.29.1' + def daggerVersion = '2.31' def work_version = '2.4.0' def retrofit_version = '2.6.2' @@ -160,16 +160,11 @@ dependencies { // DI implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" - compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0' - kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0' // Logging implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' - // Bus - implementation 'org.greenrobot:eventbus:3.1.1' - // Phone number https://github.com/google/libphonenumber implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.23' diff --git a/matrix-sdk-android/proguard-rules.pro b/matrix-sdk-android/proguard-rules.pro index fa860d8049..182f9473e8 100644 --- a/matrix-sdk-android/proguard-rules.pro +++ b/matrix-sdk-android/proguard-rules.pro @@ -20,14 +20,8 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile - -### EVENT BUS ### - +# BMA: Not sure I can delete this one without side effect -keepattributes *Annotation* --keepclassmembers class * { - @org.greenrobot.eventbus.Subscribe ; -} --keep enum org.greenrobot.eventbus.ThreadMode { *; } ### MOSHI ### diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 0e7088a6a5..cb49ee8818 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -86,7 +86,7 @@ class CommonTestHelper(context: Context) { * * @param session the session to sync */ - fun syncSession(session: Session) { + fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis) { val lock = CountDownLatch(1) val job = GlobalScope.launch(Dispatchers.Main) { @@ -109,7 +109,7 @@ class CommonTestHelper(context: Context) { } GlobalScope.launch(Dispatchers.Main) { syncLiveData.observeForever(syncObserver) } - await(lock) + await(lock, timeout) } /** @@ -119,7 +119,7 @@ class CommonTestHelper(context: Context) { * @param message the message to send * @param nbOfMessages the number of time the message will be sent */ - fun sendTextMessage(room: Room, message: String, nbOfMessages: Int): List { + fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List { val timeline = room.createTimeline(null, TimelineSettings(10)) val sentEvents = ArrayList(nbOfMessages) val latch = CountDownLatch(1) @@ -151,7 +151,7 @@ class CommonTestHelper(context: Context) { room.sendTextMessage(message + " #" + (i + 1)) } // Wait 3 second more per message - await(latch, timeout = TestConstants.timeOutMillis + 3_000L * nbOfMessages) + await(latch, timeout = timeout + 3_000L * nbOfMessages) timeline.dispose() // Check that all events has been created @@ -215,14 +215,14 @@ class CommonTestHelper(context: Context) { .getLoginFlow(hs, it) } - doSync { + doSync(timeout = 60_000) { matrix.authenticationService .getRegistrationWizard() .createAccount(userName, password, null, it) } // Perform dummy step - val registrationResult = doSync { + val registrationResult = doSync(timeout = 60_000) { matrix.authenticationService .getRegistrationWizard() .dummy(it) @@ -231,7 +231,7 @@ class CommonTestHelper(context: Context) { assertTrue(registrationResult is RegistrationResult.Success) val session = (registrationResult as RegistrationResult.Success).session if (sessionTestParams.withInitialSync) { - syncSession(session) + syncSession(session, 60_000) } return session diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt index 76e59d9a90..b6bedbd719 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt @@ -18,14 +18,21 @@ package org.matrix.android.sdk.common import org.matrix.android.sdk.api.session.Session -data class CryptoTestData(val firstSession: Session, - val roomId: String, - val secondSession: Session? = null, - val thirdSession: Session? = null) { +data class CryptoTestData(val roomId: String, + val sessions: List) { + + val firstSession: Session + get() = sessions.first() + + val secondSession: Session? + get() = sessions.getOrNull(1) + + val thirdSession: Session? + get() = sessions.getOrNull(2) fun cleanUp(testHelper: CommonTestHelper) { - testHelper.signOutAndClose(firstSession) - secondSession?.let { testHelper.signOutAndClose(it) } - thirdSession?.let { testHelper.signOutAndClose(it) } + sessions.forEach { + testHelper.signOutAndClose(it) + } } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index cbb22daf0f..3d5856fc64 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -73,7 +73,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) { } } - return CryptoTestData(aliceSession, roomId) + return CryptoTestData(roomId, listOf(aliceSession)) } /** @@ -139,7 +139,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) { // assertNotNull(roomFromBobPOV.powerLevels) // assertTrue(roomFromBobPOV.powerLevels.maySendMessage(bobSession.myUserId)) - return CryptoTestData(aliceSession, aliceRoomId, bobSession) + return CryptoTestData(aliceRoomId, listOf(aliceSession, bobSession)) } /** @@ -157,7 +157,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) { // wait the initial sync SystemClock.sleep(1000) - return CryptoTestData(aliceSession, aliceRoomId, cryptoTestData.secondSession, samSession) + return CryptoTestData(aliceRoomId, listOf(aliceSession, cryptoTestData.secondSession!!, samSession)) } /** @@ -381,4 +381,30 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) { } } } + + fun doE2ETestWithManyMembers(numberOfMembers: Int): CryptoTestData { + val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams) + aliceSession.cryptoService().setWarnOnUnknownDevices(false) + + val roomId = mTestHelper.doSync { + aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }, it) + } + val room = aliceSession.getRoom(roomId)!! + + mTestHelper.runBlockingTest { + room.enableEncryption() + } + + val sessions = mutableListOf(aliceSession) + for (index in 1 until numberOfMembers) { + val session = mTestHelper.createAccount("User_$index", defaultSessionParams) + mTestHelper.doSync(timeout = 600_000) { room.invite(session.myUserId, null, it) } + println("TEST -> " + session.myUserId + " invited") + mTestHelper.doSync { session.joinRoom(room.roomId, null, emptyList(), it) } + println("TEST -> " + session.myUserId + " joined") + sessions.add(session) + } + + return CryptoTestData(roomId, sessions) + } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 197e36df06..2c4d89b070 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -50,6 +50,8 @@ import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.room.model.message.MessageContent import java.util.concurrent.CountDownLatch @RunWith(AndroidJUnit4::class) @@ -296,4 +298,77 @@ class KeyShareTests : InstrumentedTest { mTestHelper.signOutAndClose(aliceSession1) mTestHelper.signOutAndClose(aliceSession2) } + + @Test + fun test_ImproperKeyShareBug() { + val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) + + mTestHelper.doSync { + aliceSession.cryptoService().crossSigningService() + .initializeCrossSigning(UserPasswordAuth( + user = aliceSession.myUserId, + password = TestConstants.PASSWORD + ), it) + } + + // Create an encrypted room and send a couple of messages + val roomId = mTestHelper.doSync { + aliceSession.createRoom( + CreateRoomParams().apply { + visibility = RoomDirectoryVisibility.PRIVATE + enableEncryption() + }, + it + ) + } + val roomAlicePov = aliceSession.getRoom(roomId) + assertNotNull(roomAlicePov) + Thread.sleep(1_000) + assertTrue(roomAlicePov?.isEncrypted() == true) + val secondEventId = mTestHelper.sendTextMessage(roomAlicePov!!, "Message", 3)[1].eventId + + // Create bob session + + val bobSession = mTestHelper.createAccount(TestConstants.USER_BOB, SessionTestParams(true)) + mTestHelper.doSync { + bobSession.cryptoService().crossSigningService() + .initializeCrossSigning(UserPasswordAuth( + user = bobSession.myUserId, + password = TestConstants.PASSWORD + ), it) + } + + // Let alice invite bob + mTestHelper.doSync { + roomAlicePov.invite(bobSession.myUserId, null, it) + } + + mTestHelper.doSync { + bobSession.joinRoom(roomAlicePov.roomId, null, emptyList(), it) + } + + // we want to discard alice outbound session + aliceSession.cryptoService().discardOutboundSession(roomAlicePov.roomId) + + // and now resend a new message to reset index to 0 + mTestHelper.sendTextMessage(roomAlicePov, "After", 1) + + val roomRoomBobPov = aliceSession.getRoom(roomId) + val beforeJoin = roomRoomBobPov!!.getTimeLineEvent(secondEventId) + + var dRes = tryOrNull { bobSession.cryptoService().decryptEvent(beforeJoin!!.root, "") } + + assert(dRes == null) + + // Try to re-ask the keys + + bobSession.cryptoService().reRequestRoomKeyForEvent(beforeJoin!!.root) + + Thread.sleep(3_000) + + // With the bug the first session would have improperly reshare that key :/ + dRes = tryOrNull { bobSession.cryptoService().decryptEvent(beforeJoin.root, "") } + Log.d("#TEST", "KS: sgould not decrypt that ${beforeJoin.root.getClearContent().toModel()?.body}") + assert(dRes?.clearEvent == null) + } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt new file mode 100644 index 0000000000..ff07cf1d1d --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.session.room.timeline + +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.runners.MethodSorters +import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.message.MessageContent +import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings +import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CryptoTestHelper +import java.util.concurrent.CountDownLatch +import kotlin.test.fail + +@RunWith(JUnit4::class) +@FixMethodOrder(MethodSorters.JVM) +class TimelineWithManyMembersTest : InstrumentedTest { + + companion object { + private const val NUMBER_OF_MEMBERS = 6 + } + + private val commonTestHelper = CommonTestHelper(context()) + private val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + + /** + * Ensures when someone sends a message to a crowded room, everyone can decrypt the message. + */ + @Test + fun everyone_should_decrypt_message_in_a_crowded_room() { + val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS) + + val sessionForFirstMember = cryptoTestData.firstSession + val roomForFirstMember = sessionForFirstMember.getRoom(cryptoTestData.roomId)!! + + val firstMessage = "First messages from Alice" + commonTestHelper.sendTextMessage( + roomForFirstMember, + firstMessage, + 1, + 600_000 + ) + + for (index in 1 until cryptoTestData.sessions.size) { + val session = cryptoTestData.sessions[index] + val roomForCurrentMember = session.getRoom(cryptoTestData.roomId)!! + val timelineForCurrentMember = roomForCurrentMember.createTimeline(null, TimelineSettings(30)) + timelineForCurrentMember.start() + + session.startSync(true) + + run { + val lock = CountDownLatch(1) + val eventsListener = commonTestHelper.createEventListener(lock) { snapshot -> + snapshot + .find { it.isEncrypted() } + ?.let { + val body = it.root.getClearContent()?.toModel()?.body + if (body?.startsWith(firstMessage).orFalse()) { + println("User " + session.myUserId + " decrypted as " + body) + return@createEventListener true + } else { + fail("User " + session.myUserId + " decrypted as " + body + " CryptoError: " + it.root.mCryptoError) + } + } ?: return@createEventListener false + } + timelineForCurrentMember.addListener(eventsListener) + commonTestHelper.await(lock, 600_000) + } + session.stopSync() + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt index 360b955869..bf21941e0c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt @@ -41,6 +41,16 @@ interface AuthenticationService { */ fun getLoginFlowOfSession(sessionId: String, callback: MatrixCallback): Cancelable + /** + * Get a SSO url + */ + fun getSsoUrl(redirectUrl: String, deviceId: String?, providerId: String?): String? + + /** + * Get the sign in or sign up fallback URL + */ + fun getFallbackUrl(forSignIn: Boolean, deviceId: String?): String? + /** * Return a LoginWizard, to login to the homeserver. The login flow has to be retrieved first. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt index 4f9c84a47c..6675fb0ff5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt @@ -37,6 +37,6 @@ class SenderNotificationPermissionCondition( fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean { val powerLevelsHelper = PowerLevelsHelper(powerLevels) - return event.senderId != null && powerLevelsHelper.getUserPowerLevelValue(event.senderId) >= powerLevelsHelper.notificationLevel(key) + return event.senderId != null && powerLevelsHelper.getUserPowerLevelValue(event.senderId) >= powerLevels.notificationLevel(key) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt index aefc086b43..ac1d726d03 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt @@ -25,7 +25,6 @@ interface PermalinkService { companion object { const val MATRIX_TO_URL_BASE = "https://matrix.to/#/" - const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://" } /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt index 696b612389..e778f5740d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt @@ -25,28 +25,85 @@ import org.matrix.android.sdk.api.session.room.powerlevels.Role */ @JsonClass(generateAdapter = true) data class PowerLevelsContent( + /** + * The level required to ban a user. Defaults to 50 if unspecified. + */ @Json(name = "ban") val ban: Int = Role.Moderator.value, + /** + * The level required to kick a user. Defaults to 50 if unspecified. + */ @Json(name = "kick") val kick: Int = Role.Moderator.value, + /** + * The level required to invite a user. Defaults to 50 if unspecified. + */ @Json(name = "invite") val invite: Int = Role.Moderator.value, + /** + * The level required to redact an event. Defaults to 50 if unspecified. + */ @Json(name = "redact") val redact: Int = Role.Moderator.value, + /** + * The default level required to send message events. Can be overridden by the events key. Defaults to 0 if unspecified. + */ @Json(name = "events_default") val eventsDefault: Int = Role.Default.value, - @Json(name = "events") val events: MutableMap = HashMap(), + /** + * The level required to send specific event types. This is a mapping from event type to power level required. + */ + @Json(name = "events") val events: Map = emptyMap(), + /** + * The default power level for every user in the room, unless their user_id is mentioned in the users key. Defaults to 0 if unspecified. + */ @Json(name = "users_default") val usersDefault: Int = Role.Default.value, - @Json(name = "users") val users: MutableMap = HashMap(), + /** + * The power levels for specific users. This is a mapping from user_id to power level for that user. + */ + @Json(name = "users") val users: Map = emptyMap(), + /** + * The default level required to send state events. Can be overridden by the events key. Defaults to 50 if unspecified. + */ @Json(name = "state_default") val stateDefault: Int = Role.Moderator.value, - @Json(name = "notifications") val notifications: Map = HashMap() + /** + * The power level requirements for specific notification types. This is a mapping from key to power level for that notifications key. + */ + @Json(name = "notifications") val notifications: Map = emptyMap() ) { /** - * Alter this content with a new power level for the specified user + * Return a copy of this content with a new power level for the specified user * * @param userId the userId to alter the power level of * @param powerLevel the new power level, or null to set the default value. */ - fun setUserPowerLevel(userId: String, powerLevel: Int?) { - if (powerLevel == null || powerLevel == usersDefault) { - users.remove(userId) - } else { - users[userId] = powerLevel + fun setUserPowerLevel(userId: String, powerLevel: Int?): PowerLevelsContent { + return copy( + users = users.toMutableMap().apply { + if (powerLevel == null || powerLevel == usersDefault) { + remove(userId) + } else { + put(userId, powerLevel) + } + } + ) + } + + /** + * Get the notification level for a dedicated key. + * + * @param key the notification key + * @return the level, default to Moderator if the key is not found + */ + fun notificationLevel(key: String): Int { + return when (val value = notifications[key]) { + // the first implementation was a string value + is String -> value.toInt() + is Double -> value.toInt() + is Int -> value + else -> Role.Moderator.value } } + + companion object { + /** + * Key to use for content.notifications and get the level required to trigger an @room notification. Defaults to 50 if unspecified. + */ + const val NOTIFICATIONS_ROOM_KEY = "room" + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt index 00fa68c0ac..280316d4b5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt @@ -27,6 +27,7 @@ data class MessageStickerContent( /** * Set in local, not from server */ + @Transient override val msgType: String = MessageType.MSGTYPE_STICKER_LOCAL, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt index 47922f6968..4f1253c6df 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt @@ -108,19 +108,4 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { val powerLevel = getUserPowerLevelValue(userId) return powerLevel >= powerLevelsContent.redact } - - /** - * Get the notification level for a dedicated key. - * - * @param key the notification key - * @return the level - */ - fun notificationLevel(key: String): Int { - return when (val value = powerLevelsContent.notifications[key]) { - // the first implementation was a string value - is String -> value.toInt() - is Int -> value - else -> Role.Moderator.value - } - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt new file mode 100644 index 0000000000..c625a7f088 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.room.state + +import org.matrix.android.sdk.api.query.QueryStringValue +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent + +/** + * Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC) + */ +fun StateService.isPublic(): Boolean { + return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition) + ?.content + ?.toModel() + ?.joinRules == RoomJoinRules.PUBLIC +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/eventbus/EventBusTimberLogger.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/UrlExtensions.kt similarity index 58% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/eventbus/EventBusTimberLogger.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/UrlExtensions.kt index 2cbd7ba7f0..17f27b2514 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/eventbus/EventBusTimberLogger.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/UrlExtensions.kt @@ -14,18 +14,24 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.eventbus +package org.matrix.android.sdk.api.util -import org.greenrobot.eventbus.Logger -import timber.log.Timber -import java.util.logging.Level +import java.net.URLEncoder -class EventBusTimberLogger : Logger { - override fun log(level: Level, msg: String) { - Timber.d(msg) +/** + * Append param and value to a Url, using "?" or "&". Value parameter will be encoded + * Return this for chaining purpose + */ +fun StringBuilder.appendParamToUrl(param: String, value: String): StringBuilder { + if (contains("?")) { + append("&") + } else { + append("?") } - override fun log(level: Level, msg: String, th: Throwable) { - Timber.e(th, msg) - } + append(param) + append("=") + append(URLEncoder.encode(value, "utf-8")) + + return this } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/Constants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt similarity index 69% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/Constants.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt index 7d18aba627..642279cc27 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/Constants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt @@ -14,25 +14,25 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.auth +package org.matrix.android.sdk.internal.auth /** * Path to use when the client does not supported any or all login flows * Ref: https://matrix.org/docs/spec/client_server/latest#login-fallback */ -const val LOGIN_FALLBACK_PATH = "/_matrix/static/client/login/" +internal const val LOGIN_FALLBACK_PATH = "/_matrix/static/client/login/" /** * Path to use when the client does not supported any or all registration flows * Not documented */ -const val REGISTER_FALLBACK_PATH = "/_matrix/static/client/register/" +internal const val REGISTER_FALLBACK_PATH = "/_matrix/static/client/register/" /** * Path to use when the client want to connect using SSO * Ref: https://matrix.org/docs/spec/client_server/latest#sso-client-login */ -const val SSO_REDIRECT_PATH = "/_matrix/client/r0/login/sso/redirect" -const val MSC2858_SSO_REDIRECT_PATH = "/_matrix/client/unstable/org.matrix.msc2858/login/sso/redirect" +internal const val SSO_REDIRECT_PATH = "/_matrix/client/r0/login/sso/redirect" +internal const val MSC2858_SSO_REDIRECT_PATH = "/_matrix/client/unstable/org.matrix.msc2858/login/sso/redirect" -const val SSO_REDIRECT_URL_PARAM = "redirectUrl" +internal const val SSO_REDIRECT_URL_PARAM = "redirectUrl" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index 55f053de8d..c99e9bd81c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.Cancelable import org.matrix.android.sdk.api.util.NoOpCancellable +import org.matrix.android.sdk.api.util.appendParamToUrl import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse import org.matrix.android.sdk.internal.auth.data.RiotConfig @@ -99,6 +100,52 @@ internal class DefaultAuthenticationService @Inject constructor( } } + override fun getSsoUrl(redirectUrl: String, deviceId: String?, providerId: String?): String? { + val homeServerUrlBase = getHomeServerUrlBase() ?: return null + + return buildString { + append(homeServerUrlBase) + if (providerId != null) { + append(MSC2858_SSO_REDIRECT_PATH) + append("/$providerId") + } else { + append(SSO_REDIRECT_PATH) + } + // Set the redirect url + appendParamToUrl(SSO_REDIRECT_URL_PARAM, redirectUrl) + deviceId?.takeIf { it.isNotBlank() }?.let { + // But https://github.com/matrix-org/synapse/issues/5755 + appendParamToUrl("device_id", it) + } + } + } + + override fun getFallbackUrl(forSignIn: Boolean, deviceId: String?): String? { + val homeServerUrlBase = getHomeServerUrlBase() ?: return null + + return buildString { + append(homeServerUrlBase) + if (forSignIn) { + append(LOGIN_FALLBACK_PATH) + deviceId?.takeIf { it.isNotBlank() }?.let { + // But https://github.com/matrix-org/synapse/issues/5755 + appendParamToUrl("device_id", it) + } + } else { + // For sign up + append(REGISTER_FALLBACK_PATH) + } + } + } + + private fun getHomeServerUrlBase(): String? { + return pendingSessionData + ?.homeServerConnectionConfig + ?.homeServerUri + ?.toString() + ?.trim { it == '/' } + } + override fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback): Cancelable { pendingSessionData = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt index c2c81894fb..7e92ff3e88 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.crypto import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried import org.matrix.android.sdk.api.session.events.model.Event @@ -60,7 +59,6 @@ internal class CancelGossipRequestWorker(context: Context, @Inject lateinit var sendToDeviceTask: SendToDeviceTask @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var eventBus: EventBus @Inject lateinit var credentials: Credentials override fun injectWith(injector: SessionComponent) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt index 4f94a27bbd..c075c90eb9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt @@ -32,6 +32,7 @@ import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.internal.crypto.model.rest.GossipingDefaultContent import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject +import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.session.SessionScope @@ -206,34 +207,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( Timber.v("## CRYPTO | GOSSIP processIncomingRoomKeyRequest from $userId:$deviceId for $roomId / ${body.sessionId} id ${request.requestId}") if (credentials.userId != userId) { - Timber.w("## CRYPTO | GOSSIP processReceivedGossipingRequests() : room key request from other user") - val senderKey = body.senderKey ?: return Unit - .also { Timber.w("missing senderKey") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - val sessionId = body.sessionId ?: return Unit - .also { Timber.w("missing sessionId") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - - if (alg != MXCRYPTO_ALGORITHM_MEGOLM) { - return Unit - .also { Timber.w("Only megolm is accepted here") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - } - - val roomEncryptor = roomEncryptorsStore.get(roomId) ?: return Unit - .also { Timber.w("no room Encryptor") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - val isSuccess = roomEncryptor.reshareKey(sessionId, userId, deviceId, senderKey) - - if (isSuccess) { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTED) - } else { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.UNABLE_TO_PROCESS) - } - } - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.RE_REQUESTED) + handleKeyRequestFromOtherUser(body, request, alg, roomId, userId, deviceId) return } // TODO: should we queue up requests we don't yet have keys for, in case they turn up later? @@ -291,6 +265,42 @@ internal class IncomingGossipingRequestManager @Inject constructor( onRoomKeyRequest(request) } + private fun handleKeyRequestFromOtherUser(body: RoomKeyRequestBody, + request: IncomingRoomKeyRequest, + alg: String, + roomId: String, + userId: String, + deviceId: String) { + Timber.w("## CRYPTO | GOSSIP processReceivedGossipingRequests() : room key request from other user") + val senderKey = body.senderKey ?: return Unit + .also { Timber.w("missing senderKey") } + .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } + val sessionId = body.sessionId ?: return Unit + .also { Timber.w("missing sessionId") } + .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } + + if (alg != MXCRYPTO_ALGORITHM_MEGOLM) { + return Unit + .also { Timber.w("Only megolm is accepted here") } + .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } + } + + val roomEncryptor = roomEncryptorsStore.get(roomId) ?: return Unit + .also { Timber.w("no room Encryptor") } + .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } + + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { + val isSuccess = roomEncryptor.reshareKey(sessionId, userId, deviceId, senderKey) + + if (isSuccess) { + cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTED) + } else { + cryptoStore.updateGossipingRequestState(request, GossipingRequestState.UNABLE_TO_PROCESS) + } + } + cryptoStore.updateGossipingRequestState(request, GossipingRequestState.RE_REQUESTED) + } + private fun processIncomingSecretShareRequest(request: IncomingSecretShareRequest) { val secretName = request.secretName ?: return Unit.also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt index c952602d93..b1e91e8d50 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt @@ -19,6 +19,8 @@ package org.matrix.android.sdk.internal.crypto import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXOutboundSessionInfo +import org.matrix.android.sdk.internal.crypto.algorithms.megolm.SharedWithHelper import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper @@ -46,7 +48,7 @@ internal class MXOlmDevice @Inject constructor( */ private val store: IMXCryptoStore, private val inboundGroupSessionStore: InboundGroupSessionStore - ) { +) { /** * @return the Curve25519 key for the account. @@ -63,11 +65,15 @@ internal class MXOlmDevice @Inject constructor( // The OLM lib utility instance. private var olmUtility: OlmUtility? = null + private data class GroupSessionCacheItem( + val groupId: String, + val groupSession: OlmOutboundGroupSession + ) + // The outbound group session. - // They are not stored in 'store' to avoid to remember to which devices we sent the session key. - // Plus, in cryptography, it is good to refresh sessions from time to time. - // The key is the session id, the value the outbound group session. - private val outboundGroupSessionStore: MutableMap = HashMap() + // Caches active outbound session to avoid to sync with DB before read + // The key is the session id, the value the . + private val outboundGroupSessionCache: MutableMap = HashMap() // Store a set of decrypted message indexes for each group session. // This partially mitigates a replay attack where a MITM resends a group @@ -135,6 +141,10 @@ internal class MXOlmDevice @Inject constructor( */ fun release() { olmUtility?.releaseUtility() + outboundGroupSessionCache.values.forEach { + it.groupSession.releaseSession() + } + outboundGroupSessionCache.clear() } /** @@ -406,11 +416,12 @@ internal class MXOlmDevice @Inject constructor( * * @return the session id for the outbound session. */ - fun createOutboundGroupSession(): String? { + fun createOutboundGroupSessionForRoom(roomId: String): String? { var session: OlmOutboundGroupSession? = null try { session = OlmOutboundGroupSession() - outboundGroupSessionStore[session.sessionIdentifier()] = session + outboundGroupSessionCache[session.sessionIdentifier()] = GroupSessionCacheItem(roomId, session) + store.storeCurrentOutboundGroupSessionForRoom(roomId, session) return session.sessionIdentifier() } catch (e: Exception) { Timber.e(e, "createOutboundGroupSession") @@ -421,6 +432,39 @@ internal class MXOlmDevice @Inject constructor( return null } + fun storeOutboundGroupSessionForRoom(roomId: String, sessionId: String) { + outboundGroupSessionCache[sessionId]?.let { + store.storeCurrentOutboundGroupSessionForRoom(roomId, it.groupSession) + } + } + + fun restoreOutboundGroupSessionForRoom(roomId: String): MXOutboundSessionInfo? { + val restoredOutboundGroupSession = store.getCurrentOutboundGroupSessionForRoom(roomId) + if (restoredOutboundGroupSession != null) { + val sessionId = restoredOutboundGroupSession.outboundGroupSession.sessionIdentifier() + // cache it + outboundGroupSessionCache[sessionId] = GroupSessionCacheItem(roomId, restoredOutboundGroupSession.outboundGroupSession) + + return MXOutboundSessionInfo( + sessionId = sessionId, + sharedWithHelper = SharedWithHelper(roomId, sessionId, store), + restoredOutboundGroupSession.creationTime + ) + } + return null + } + + fun discardOutboundGroupSessionForRoom(roomId: String) { + val toDiscard = outboundGroupSessionCache.filter { + it.value.groupId == roomId + } + toDiscard.forEach { (sessionId, cacheItem) -> + cacheItem.groupSession.releaseSession() + outboundGroupSessionCache.remove(sessionId) + } + store.storeCurrentOutboundGroupSessionForRoom(roomId, null) + } + /** * Get the current session key of an outbound group session. * @@ -430,7 +474,7 @@ internal class MXOlmDevice @Inject constructor( fun getSessionKey(sessionId: String): String? { if (sessionId.isNotEmpty()) { try { - return outboundGroupSessionStore[sessionId]!!.sessionKey() + return outboundGroupSessionCache[sessionId]!!.groupSession.sessionKey() } catch (e: Exception) { Timber.e(e, "## getSessionKey() : failed") } @@ -446,7 +490,7 @@ internal class MXOlmDevice @Inject constructor( */ fun getMessageIndex(sessionId: String): Int { return if (sessionId.isNotEmpty()) { - outboundGroupSessionStore[sessionId]!!.messageIndex() + outboundGroupSessionCache[sessionId]!!.groupSession.messageIndex() } else 0 } @@ -460,7 +504,7 @@ internal class MXOlmDevice @Inject constructor( fun encryptGroupMessage(sessionId: String, payloadString: String): String? { if (sessionId.isNotEmpty() && payloadString.isNotEmpty()) { try { - return outboundGroupSessionStore[sessionId]!!.encryptMessage(payloadString) + return outboundGroupSessionCache[sessionId]!!.groupSession.encryptMessage(payloadString) } catch (e: Exception) { Timber.e(e, "## encryptGroupMessage() : failed") } @@ -747,7 +791,7 @@ internal class MXOlmDevice @Inject constructor( throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_SENDER_KEY, MXCryptoError.ERROR_MISSING_PROPERTY_REASON) } - val session = inboundGroupSessionStore.getInboundGroupSession(sessionId, senderKey) + val session = inboundGroupSessionStore.getInboundGroupSession(sessionId, senderKey) if (session != null) { // Check that the room id matches the original one for the session. This stops diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt index 085469e9d9..e8d567b944 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.crypto import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried import org.matrix.android.sdk.api.session.events.model.Event @@ -52,7 +51,6 @@ internal class SendGossipRequestWorker(context: Context, @Inject lateinit var sendToDeviceTask: SendToDeviceTask @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var eventBus: EventBus @Inject lateinit var credentials: Credentials override fun injectWith(injector: SessionComponent) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt index bcaa16f356..8c68057056 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.crypto import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried import org.matrix.android.sdk.api.session.events.model.Event @@ -54,7 +53,6 @@ internal class SendGossipWorker(context: Context, @Inject lateinit var sendToDeviceTask: SendToDeviceTask @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var eventBus: EventBus @Inject lateinit var credentials: Credentials @Inject lateinit var messageEncrypter: MessageEncrypter @Inject lateinit var ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index fd431ce735..fa8acafb83 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -68,6 +68,10 @@ internal class MXMegolmEncryption( // case outboundSession.shareOperation will be non-null.) private var outboundSession: MXOutboundSessionInfo? = null + init { + // restore existing outbound session if any + outboundSession = olmDevice.restoreOutboundGroupSessionForRoom(roomId) + } // Default rotation periods // TODO: Make it configurable via parameters // Session rotation periods @@ -86,6 +90,9 @@ internal class MXMegolmEncryption( return encryptContent(outboundSession, eventType, eventContent) .also { notifyWithheldForSession(devices.withHeldDevices, outboundSession) + // annoyingly we have to serialize again the saved outbound session to store message index :/ + // if not we would see duplicate message index errors + olmDevice.storeOutboundGroupSessionForRoom(roomId, outboundSession.sessionId) } } @@ -107,6 +114,7 @@ internal class MXMegolmEncryption( override fun discardSessionKey() { outboundSession = null + olmDevice.discardOutboundGroupSessionForRoom(roomId) } /** @@ -116,7 +124,7 @@ internal class MXMegolmEncryption( */ private fun prepareNewSessionInRoom(): MXOutboundSessionInfo { Timber.v("## CRYPTO | prepareNewSessionInRoom() ") - val sessionId = olmDevice.createOutboundGroupSession() + val sessionId = olmDevice.createOutboundGroupSessionForRoom(roomId) val keysClaimedMap = HashMap() keysClaimedMap["ed25519"] = olmDevice.deviceEd25519Key!! @@ -152,7 +160,7 @@ internal class MXMegolmEncryption( val deviceIds = devicesInRoom.getUserDeviceIds(userId) for (deviceId in deviceIds!!) { val deviceInfo = devicesInRoom.getObject(userId, deviceId) - if (deviceInfo != null && !cryptoStore.wasSessionSharedWithUser(roomId, safeSession.sessionId, userId, deviceId).found) { + if (deviceInfo != null && !cryptoStore.getSharedSessionInfo(roomId, safeSession.sessionId, userId, deviceId).found) { val devices = shareMap.getOrPut(userId) { ArrayList() } devices.add(deviceInfo) } @@ -401,11 +409,18 @@ internal class MXMegolmEncryption( .also { Timber.w("## Crypto reshareKey: Device not found") } // Get the chain index of the key we previously sent this device - val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId, deviceId) ?: return false + val wasSessionSharedWithUser = cryptoStore.getSharedSessionInfo(roomId, sessionId, userId, deviceId) + if (!wasSessionSharedWithUser.found) { + // This session was never shared with this user + // Send a room key with held + notifyKeyWithHeld(listOf(UserDevice(userId, deviceId)), sessionId, senderKey, WithHeldCode.UNAUTHORISED) + Timber.w("## Crypto reshareKey: ERROR : Never shared megolm with this device") + return false + } + // if found chain index should not be null + val chainIndex = wasSessionSharedWithUser.chainIndex ?: return false .also { - // Send a room key with held - notifyKeyWithHeld(listOf(UserDevice(userId, deviceId)), sessionId, senderKey, WithHeldCode.UNAUTHORISED) - Timber.w("## Crypto reshareKey: ERROR : Never share megolm with this device") + Timber.w("## Crypto reshareKey: Null chain index") } val devicesByUser = mapOf(userId to listOf(deviceInfo)) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt index 9244b4d5e7..5a68937868 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt @@ -23,9 +23,9 @@ import timber.log.Timber internal class MXOutboundSessionInfo( // The id of the session val sessionId: String, - val sharedWithHelper: SharedWithHelper) { - // When the session was created - private val creationTime = System.currentTimeMillis() + val sharedWithHelper: SharedWithHelper, + // When the session was created + private val creationTime: Long = System.currentTimeMillis()) { // Number of times this session has been used var useCount: Int = 0 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt index 921f9b2cdc..f17168a6d2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt @@ -28,10 +28,6 @@ internal class SharedWithHelper( return cryptoStore.getSharedWithInfo(roomId, sessionId) } - fun wasSharedWith(userId: String, deviceId: String): Int? { - return cryptoStore.wasSessionSharedWithUser(roomId, sessionId, userId, deviceId).chainIndex - } - fun markedSessionAsShared(userId: String, deviceId: String, chainIndex: Int) { cryptoStore.markedSessionAsShared(roomId, sessionId, userId, deviceId, chainIndex) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt index 36b667911d..5c59cfd80e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt @@ -19,20 +19,20 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface CreateKeysBackupVersionTask : Task internal class DefaultCreateKeysBackupVersionTask @Inject constructor( private val roomKeysApi: RoomKeysApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : CreateKeysBackupVersionTask { override suspend fun execute(params: CreateKeysBackupVersionBody): KeysVersion { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomKeysApi.createKeysBackupVersion(params) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt index d174be20a2..ec09da7240 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface DeleteBackupTask : Task { @@ -30,11 +30,11 @@ internal interface DeleteBackupTask : Task { internal class DefaultDeleteBackupTask @Inject constructor( private val roomKeysApi: RoomKeysApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : DeleteBackupTask { override suspend fun execute(params: DeleteBackupTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomKeysApi.deleteBackup(params.version) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt index 6826596ba4..9c477efb78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface DeleteRoomSessionDataTask : Task { @@ -32,11 +32,11 @@ internal interface DeleteRoomSessionDataTask : Task { @@ -31,11 +31,11 @@ internal interface DeleteRoomSessionsDataTask : Task { @@ -30,11 +30,11 @@ internal interface DeleteSessionsDataTask : Task internal class DefaultGetKeysBackupLastVersionTask @Inject constructor( private val roomKeysApi: RoomKeysApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetKeysBackupLastVersionTask { override suspend fun execute(params: Unit): KeysVersionResult { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomKeysApi.getKeysBackupLastVersion() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt index dd2dd70e4d..13c99fb0f4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt @@ -18,20 +18,20 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetKeysBackupVersionTask : Task internal class DefaultGetKeysBackupVersionTask @Inject constructor( private val roomKeysApi: RoomKeysApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetKeysBackupVersionTask { override suspend fun execute(params: String): KeysVersionResult { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomKeysApi.getKeysBackupVersion(params) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt index 8ca03491a1..168020d9cd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeyBackupData +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetRoomSessionDataTask : Task { @@ -33,11 +33,11 @@ internal interface GetRoomSessionDataTask : Task { @@ -32,11 +32,11 @@ internal interface GetRoomSessionsDataTask : Task { @@ -31,11 +31,11 @@ internal interface GetSessionsDataTask : Task { @@ -35,11 +35,11 @@ internal interface StoreRoomSessionDataTask : Task { @@ -34,11 +34,11 @@ internal interface StoreRoomSessionsDataTask : Task { @@ -33,11 +33,11 @@ internal interface StoreSessionsDataTask : Task { @@ -32,11 +32,11 @@ internal interface UpdateKeysBackupVersionTask : Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index 6b83c4f7d1..369a4976c9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -47,6 +47,7 @@ import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper +import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody @@ -73,6 +74,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSess import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity @@ -95,6 +97,7 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.olm.OlmAccount import org.matrix.olm.OlmException +import org.matrix.olm.OlmOutboundGroupSession import timber.log.Timber import javax.inject.Inject import kotlin.collections.set @@ -756,6 +759,42 @@ internal class RealmCryptoStore @Inject constructor( return inboundGroupSessionToRelease[key] } + override fun getCurrentOutboundGroupSessionForRoom(roomId: String): OutboundGroupSessionWrapper? { + return doWithRealm(realmConfiguration) { realm -> + realm.where() + .equalTo(CryptoRoomEntityFields.ROOM_ID, roomId) + .findFirst()?.outboundSessionInfo?.let { entity -> + entity.getOutboundGroupSession()?.let { + OutboundGroupSessionWrapper( + it, + entity.creationTime ?: 0 + ) + } + } + } + } + + override fun storeCurrentOutboundGroupSessionForRoom(roomId: String, outboundGroupSession: OlmOutboundGroupSession?) { + // we can do this async, as it's just for restoring on next launch + // the olmdevice is caching the active instance + // this is called for each sent message (so not high frequency), thus we can use basic realm async without + // risk of reaching max async operation limit? + doRealmTransactionAsync(realmConfiguration) { realm -> + CryptoRoomEntity.getById(realm, roomId)?.let { entity -> + // we should delete existing outbound session info if any + entity.outboundSessionInfo?.deleteFromRealm() + + if (outboundGroupSession != null) { + val info = realm.createObject(OutboundGroupSessionInfoEntity::class.java).apply { + creationTime = System.currentTimeMillis() + putOutboundGroupSession(outboundGroupSession) + } + entity.outboundSessionInfo = info + } + } + } + } + /** * Note: the result will be only use to export all the keys and not to use the OlmInboundGroupSessionWrapper2, * so there is no need to use or update `inboundGroupSessionToRelease` for native memory management @@ -1645,7 +1684,7 @@ internal class RealmCryptoStore @Inject constructor( } } - override fun wasSessionSharedWithUser(roomId: String?, sessionId: String, userId: String, deviceId: String): IMXCryptoStore.SharedSessionResult { + override fun getSharedSessionInfo(roomId: String?, sessionId: String, userId: String, deviceId: String): IMXCryptoStore.SharedSessionResult { return doWithRealm(realmConfiguration) { realm -> SharedSessionEntity.get(realm, roomId, sessionId, userId, deviceId)?.let { IMXCryptoStore.SharedSessionResult(true, it.chainIndex) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt index 08806b0627..bca7914388 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt @@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.di.SerializeNulls import io.realm.DynamicRealm import io.realm.RealmMigration import io.realm.RealmObjectSchema +import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntityFields import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 import timber.log.Timber import javax.inject.Inject @@ -55,7 +56,7 @@ internal class RealmCryptoStoreMigration @Inject constructor(private val crossSi // 0, 1, 2: legacy Riot-Android // 3: migrate to RiotX schema // 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6) - const val CRYPTO_STORE_SCHEMA_VERSION = 11L + const val CRYPTO_STORE_SCHEMA_VERSION = 12L } private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema { @@ -93,6 +94,7 @@ internal class RealmCryptoStoreMigration @Inject constructor(private val crossSi if (oldVersion <= 8) migrateTo9(realm) if (oldVersion <= 9) migrateTo10(realm) if (oldVersion <= 10) migrateTo11(realm) + if (oldVersion <= 11) migrateTo12(realm) } private fun migrateTo1Legacy(realm: DynamicRealm) { @@ -483,4 +485,16 @@ internal class RealmCryptoStoreMigration @Inject constructor(private val crossSi realm.schema.get("CryptoMetadataEntity") ?.addField(CryptoMetadataEntityFields.DEVICE_KEYS_SENT_TO_SERVER, Boolean::class.java) } + + // Version 12L added outbound group session persistence + private fun migrateTo12(realm: DynamicRealm) { + Timber.d("Step 11 -> 12") + val outboundEntitySchema = realm.schema.create("OutboundGroupSessionInfoEntity") + .addField(OutboundGroupSessionInfoEntityFields.SERIALIZED_OUTBOUND_SESSION_DATA, String::class.java) + .addField(OutboundGroupSessionInfoEntityFields.CREATION_TIME, Long::class.java) + .setNullable(OutboundGroupSessionInfoEntityFields.CREATION_TIME, true) + + realm.schema.get("CryptoRoomEntity") + ?.addRealmObjectField(CryptoRoomEntityFields.OUTBOUND_SESSION_INFO.`$`, outboundEntitySchema) + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt index a453fc3ed0..6aae68c83e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntity import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity import io.realm.annotations.RealmModule +import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntity /** * Realm module for Crypto store classes @@ -54,6 +55,7 @@ import io.realm.annotations.RealmModule OutgoingGossipingRequestEntity::class, MyDeviceLastSeenInfoEntity::class, WithHeldSessionEntity::class, - SharedSessionEntity::class + SharedSessionEntity::class, + OutboundGroupSessionInfoEntity::class ]) internal class RealmCryptoStoreModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt index 4c19b5eb0e..e226f3eaa8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt @@ -23,7 +23,12 @@ internal open class CryptoRoomEntity( @PrimaryKey var roomId: String? = null, var algorithm: String? = null, var shouldEncryptForInvitedMembers: Boolean? = null, - var blacklistUnverifiedDevices: Boolean = false) + var blacklistUnverifiedDevices: Boolean = false, + // Store the current outbound session for this room, + // to avoid re-create and re-share at each startup (if rotation not needed..) + // This is specific to megolm but not sure how to model it better + var outboundSessionInfo: OutboundGroupSessionInfoEntity? = null + ) : RealmObject() { companion object diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutboundGroupSessionInfoEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutboundGroupSessionInfoEntity.kt new file mode 100644 index 0000000000..d50db78415 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutboundGroupSessionInfoEntity.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.crypto.store.db.model + +import io.realm.RealmObject +import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm +import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm +import org.matrix.olm.OlmOutboundGroupSession +import timber.log.Timber + +internal open class OutboundGroupSessionInfoEntity( + var serializedOutboundSessionData: String? = null, + var creationTime: Long? = null +) : RealmObject() { + + fun getOutboundGroupSession(): OlmOutboundGroupSession? { + return try { + deserializeFromRealm(serializedOutboundSessionData) + } catch (failure: Throwable) { + Timber.e(failure, "## getOutboundGroupSession() Deserialization failure") + return null + } + } + + fun putOutboundGroupSession(olmOutboundGroupSession: OlmOutboundGroupSession?) { + serializedOutboundSessionData = serializeForRealm(olmOutboundGroupSession) + } + + companion object +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt index ae72c7198a..3df6312adb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt @@ -21,9 +21,9 @@ import org.matrix.android.sdk.internal.crypto.model.MXKey import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimBody import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import timber.log.Timber import javax.inject.Inject @@ -36,13 +36,13 @@ internal interface ClaimOneTimeKeysForUsersDeviceTask : Task { val body = KeysClaimBody(oneTimeKeys = params.usersDevicesKeyTypesMap.map) - val keysClaimResponse = executeRequest(eventBus) { + val keysClaimResponse = executeRequest(globalErrorReceiver) { apiCall = cryptoApi.claimOneTimeKeysForUsersDevices(body) } val map = MXUsersDevicesMap() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt index e5078d5b4e..8f1569a037 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt @@ -20,9 +20,9 @@ import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface DeleteDeviceTask : Task { @@ -33,12 +33,12 @@ internal interface DeleteDeviceTask : Task { internal class DefaultDeleteDeviceTask @Inject constructor( private val cryptoApi: CryptoApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : DeleteDeviceTask { override suspend fun execute(params: DeleteDeviceTask.Params) { try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = cryptoApi.deleteDevice(params.deviceId, DeleteDeviceParams()) } } catch (throwable: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceWithUserPasswordTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceWithUserPasswordTask.kt index 38eee7f932..b4c1e6d27c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceWithUserPasswordTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceWithUserPasswordTask.kt @@ -21,9 +21,9 @@ import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface DeleteDeviceWithUserPasswordTask : Task { @@ -37,11 +37,11 @@ internal interface DeleteDeviceWithUserPasswordTask : Task { @@ -35,7 +35,7 @@ internal interface DownloadKeysForUsersTask : Task { @@ -29,11 +29,11 @@ internal interface GetDeviceInfoTask : Task internal class DefaultGetDevicesTask @Inject constructor( private val cryptoApi: CryptoApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetDevicesTask { override suspend fun execute(params: Unit): DevicesListResponse { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = cryptoApi.getDevices() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetKeyChangesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetKeyChangesTask.kt index 289a5226f5..4cc9ab2fcb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetKeyChangesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetKeyChangesTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.KeyChangesResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetKeyChangesTask : Task { @@ -34,11 +34,11 @@ internal interface GetKeyChangesTask : Task { internal class DefaultRedactEventTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus) : RedactEventTask { + private val globalErrorReceiver: GlobalErrorReceiver) : RedactEventTask { override suspend fun execute(params: RedactEventTask.Params): String { - val executeRequest = executeRequest(eventBus) { + val executeRequest = executeRequest(globalErrorReceiver) { apiCall = roomAPI.redactEvent( txId = params.txID, roomId = params.roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt index 8b739c4b64..b772bfbce2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt @@ -15,11 +15,12 @@ */ package org.matrix.android.sdk.internal.crypto.tasks -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI +import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository import org.matrix.android.sdk.internal.session.room.send.SendResponse import org.matrix.android.sdk.internal.task.Task @@ -35,16 +36,24 @@ internal interface SendEventTask : Task { internal class DefaultSendEventTask @Inject constructor( private val localEchoRepository: LocalEchoRepository, private val encryptEventTask: DefaultEncryptEventTask, + private val loadRoomMembersTask: LoadRoomMembersTask, private val roomAPI: RoomAPI, - private val eventBus: EventBus) : SendEventTask { + private val globalErrorReceiver: GlobalErrorReceiver) : SendEventTask { override suspend fun execute(params: SendEventTask.Params): String { try { + // Make sure to load all members in the room before sending the event. + params.event.roomId + ?.takeIf { params.encrypt } + ?.let { roomId -> + loadRoomMembersTask.execute(LoadRoomMembersTask.Params(roomId)) + } + val event = handleEncryption(params) val localId = event.eventId!! localEchoRepository.updateSendState(localId, params.event.roomId, SendState.SENDING) - val executeRequest = executeRequest(eventBus) { + val executeRequest = executeRequest(globalErrorReceiver) { apiCall = roomAPI.send( localId, roomId = event.roomId ?: "", diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt index 37e0bbc887..d2af91601b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt @@ -19,9 +19,9 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceBody +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject import kotlin.random.Random @@ -38,7 +38,7 @@ internal interface SendToDeviceTask : Task { internal class DefaultSendToDeviceTask @Inject constructor( private val cryptoApi: CryptoApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SendToDeviceTask { override suspend fun execute(params: SendToDeviceTask.Params) { @@ -46,7 +46,7 @@ internal class DefaultSendToDeviceTask @Inject constructor( messages = params.contentMap.map ) - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = cryptoApi.sendToDevice( params.eventType, params.transactionId ?: Random.nextInt(Integer.MAX_VALUE).toString(), diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt index cedb7a6618..c39dfb1016 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt @@ -15,10 +15,10 @@ */ package org.matrix.android.sdk.internal.crypto.tasks -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository @@ -37,7 +37,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor( private val encryptEventTask: DefaultEncryptEventTask, private val roomAPI: RoomAPI, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, - private val eventBus: EventBus) : SendVerificationMessageTask { + private val globalErrorReceiver: GlobalErrorReceiver) : SendVerificationMessageTask { override suspend fun execute(params: SendVerificationMessageTask.Params): String { val event = handleEncryption(params) @@ -45,7 +45,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor( try { localEchoRepository.updateSendState(localId, event.roomId, SendState.SENDING) - val executeRequest = executeRequest(eventBus) { + val executeRequest = executeRequest(globalErrorReceiver) { apiCall = roomAPI.send( localId, roomId = event.roomId ?: "", diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SetDeviceNameTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SetDeviceNameTask.kt index 51b9624554..b835d46236 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SetDeviceNameTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SetDeviceNameTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.UpdateDeviceInfoBody +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface SetDeviceNameTask : Task { @@ -34,14 +34,14 @@ internal interface SetDeviceNameTask : Task { internal class DefaultSetDeviceNameTask @Inject constructor( private val cryptoApi: CryptoApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SetDeviceNameTask { override suspend fun execute(params: SetDeviceNameTask.Params) { val body = UpdateDeviceInfoBody( displayName = params.deviceName ) - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = cryptoApi.updateDeviceInfo(params.deviceId, body) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt index 6216a3a305..eb53bbbf8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt @@ -21,9 +21,9 @@ import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.DeviceKeys import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadBody import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import timber.log.Timber import javax.inject.Inject @@ -38,7 +38,7 @@ internal interface UploadKeysTask : Task $body") - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = cryptoApi.uploadKeys(body) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt index a4e10ddbfc..c50faf37b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.SignatureUploadResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface UploadSignaturesTask : Task { @@ -31,12 +31,12 @@ internal interface UploadSignaturesTask : Task(eventBus) { + val response = executeRequest(globalErrorReceiver) { this.isRetryable = true this.maxRetryCount = 10 this.apiCall = cryptoApi.uploadSignatures(params.signatures) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt index 038ef9dbd3..cceff355bb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt @@ -25,9 +25,9 @@ import org.matrix.android.sdk.internal.crypto.model.rest.KeysQueryResponse import org.matrix.android.sdk.internal.crypto.model.rest.UploadSigningKeysBody import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth import org.matrix.android.sdk.internal.crypto.model.toRest +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface UploadSigningKeysTask : Task { @@ -55,7 +55,7 @@ data class UploadSigningKeys(val failures: Map?) : Failure.FeatureF internal class DefaultUploadSigningKeysTask @Inject constructor( private val cryptoApi: CryptoApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : UploadSigningKeysTask { override suspend fun execute(params: UploadSigningKeysTask.Params) { @@ -87,7 +87,7 @@ internal class DefaultUploadSigningKeysTask @Inject constructor( } private suspend fun doRequest(uploadQuery: UploadSigningKeysBody) { - val keysQueryResponse = executeRequest(eventBus) { + val keysQueryResponse = executeRequest(globalErrorReceiver) { apiCall = cryptoApi.uploadSigningKeys(uploadQuery) } if (keysQueryResponse.failures?.isNotEmpty() == true) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index b970ec60e2..57002b5a60 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -21,6 +21,8 @@ import io.realm.RealmMigration import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields +import org.matrix.android.sdk.internal.database.model.RoomEntityFields +import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import timber.log.Timber import javax.inject.Inject @@ -28,7 +30,7 @@ import javax.inject.Inject class RealmSessionStoreMigration @Inject constructor() : RealmMigration { companion object { - const val SESSION_STORE_SCHEMA_VERSION = 6L + const val SESSION_STORE_SCHEMA_VERSION = 7L } override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { @@ -40,6 +42,7 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration { if (oldVersion <= 3) migrateTo4(realm) if (oldVersion <= 4) migrateTo5(realm) if (oldVersion <= 5) migrateTo6(realm) + if (oldVersion <= 6) migrateTo7(realm) } private fun migrateTo1(realm: DynamicRealm) { @@ -105,4 +108,18 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration { .addField(PreviewUrlCacheEntityFields.MXC_URL, String::class.java) .addField(PreviewUrlCacheEntityFields.LAST_UPDATED_TIMESTAMP, Long::class.java) } + + private fun migrateTo7(realm: DynamicRealm) { + Timber.d("Step 6 -> 7") + realm.schema.get("RoomEntity") + ?.addField(RoomEntityFields.MEMBERS_LOAD_STATUS_STR, String::class.java) + ?.transform { obj -> + if (obj.getBoolean("areAllMembersLoaded")) { + obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.LOADED.name) + } else { + obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.NONE.name) + } + } + ?.removeField("areAllMembersLoaded") + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt index 9af1646a4c..3ff2532604 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt @@ -23,8 +23,7 @@ import io.realm.annotations.PrimaryKey internal open class RoomEntity(@PrimaryKey var roomId: String = "", var chunks: RealmList = RealmList(), - var sendingTimelineEvents: RealmList = RealmList(), - var areAllMembersLoaded: Boolean = false + var sendingTimelineEvents: RealmList = RealmList() ) : RealmObject() { private var membershipStr: String = Membership.NONE.name @@ -36,5 +35,14 @@ internal open class RoomEntity(@PrimaryKey var roomId: String = "", membershipStr = value.name } + private var membersLoadStatusStr: String = RoomMembersLoadStatusType.NONE.name + var membersLoadStatus: RoomMembersLoadStatusType + get() { + return RoomMembersLoadStatusType.valueOf(membersLoadStatusStr) + } + set(value) { + membersLoadStatusStr = value.name + } + companion object } diff --git a/vector/src/main/java/im/vector/app/core/di/VectorAssistedModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomMembersLoadStatusType.kt similarity index 68% rename from vector/src/main/java/im/vector/app/core/di/VectorAssistedModule.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomMembersLoadStatusType.kt index 78a935a1d4..79fe17253b 100644 --- a/vector/src/main/java/im/vector/app/core/di/VectorAssistedModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomMembersLoadStatusType.kt @@ -1,11 +1,11 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -14,9 +14,10 @@ * limitations under the License. */ -package im.vector.app.core.di +package org.matrix.android.sdk.internal.database.model -/* -@Module(includes = [AssistedInject_VectorAssistedModule::class]) -@AssistedModule -class VectorAssistedModule*/ +internal enum class RoomMembersLoadStatusType { + NONE, + LOADING, + LOADED +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorHandler.kt new file mode 100644 index 0000000000..9afdb40ed1 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorHandler.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2021 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.network + +import org.matrix.android.sdk.api.failure.GlobalError +import org.matrix.android.sdk.internal.auth.SessionParamsStore +import org.matrix.android.sdk.internal.di.SessionId +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.task.TaskExecutor +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +@SessionScope +internal class GlobalErrorHandler @Inject constructor( + private val taskExecutor: TaskExecutor, + private val sessionParamsStore: SessionParamsStore, + @SessionId private val sessionId: String +) : GlobalErrorReceiver { + + var listener: Listener? = null + + override fun handleGlobalError(globalError: GlobalError) { + Timber.e("Global error received: $globalError") + + if (globalError is GlobalError.InvalidToken && globalError.softLogout) { + // Mark the token has invalid + taskExecutor.executorScope.launch(Dispatchers.IO) { + sessionParamsStore.setTokenInvalid(sessionId) + } + } + + listener?.onGlobalError(globalError) + } + + internal interface Listener { + fun onGlobalError(globalError: GlobalError) + } +} diff --git a/vector/src/main/java/im/vector/app/core/di/AssistedInjectModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorReceiver.kt similarity index 63% rename from vector/src/main/java/im/vector/app/core/di/AssistedInjectModule.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorReceiver.kt index 0ba4bedb92..47607ba893 100644 --- a/vector/src/main/java/im/vector/app/core/di/AssistedInjectModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/GlobalErrorReceiver.kt @@ -1,11 +1,11 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright 2021 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -14,11 +14,10 @@ * limitations under the License. */ -package im.vector.app.core.di +package org.matrix.android.sdk.internal.network -import com.squareup.inject.assisted.dagger2.AssistedModule -import dagger.Module +import org.matrix.android.sdk.api.failure.GlobalError -@AssistedModule -@Module(includes = [AssistedInject_AssistedInjectModule::class]) -interface AssistedInjectModule +internal interface GlobalErrorReceiver { + fun handleGlobalError(globalError: GlobalError) +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt index 2535a5347a..442029127d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.network import kotlinx.coroutines.CancellationException import kotlinx.coroutines.delay -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.shouldBeRetried import org.matrix.android.sdk.internal.network.ssl.CertUtil @@ -27,10 +26,10 @@ import retrofit2.awaitResponse import timber.log.Timber import java.io.IOException -internal suspend inline fun executeRequest(eventBus: EventBus?, - block: Request.() -> Unit) = Request(eventBus).apply(block).execute() +internal suspend inline fun executeRequest(globalErrorReceiver: GlobalErrorReceiver?, + block: Request.() -> Unit) = Request(globalErrorReceiver).apply(block).execute() -internal class Request(private val eventBus: EventBus?) { +internal class Request(private val globalErrorReceiver: GlobalErrorReceiver?) { var isRetryable = false var initialDelay: Long = 100L @@ -47,7 +46,7 @@ internal class Request(private val eventBus: EventBus?) { response.body() ?: throw IllegalStateException("The request returned a null body") } else { - throw response.toFailure(eventBus) + throw response.toFailure(globalErrorReceiver) } } catch (exception: Throwable) { // Log some details about the request which has failed diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt index c54af571d8..dd5a69dd3c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt @@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.internal.di.MoshiProvider import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.ResponseBody -import org.greenrobot.eventbus.EventBus import retrofit2.Response import timber.log.Timber import java.io.IOException @@ -54,18 +53,18 @@ internal suspend fun okhttp3.Call.awaitResponse(): okhttp3.Response { /** * Convert a retrofit Response to a Failure, and eventually parse errorBody to convert it to a MatrixError */ -internal fun Response.toFailure(eventBus: EventBus?): Failure { - return toFailure(errorBody(), code(), eventBus) +internal fun Response.toFailure(globalErrorReceiver: GlobalErrorReceiver?): Failure { + return toFailure(errorBody(), code(), globalErrorReceiver) } /** * Convert a okhttp3 Response to a Failure, and eventually parse errorBody to convert it to a MatrixError */ -internal fun okhttp3.Response.toFailure(eventBus: EventBus?): Failure { - return toFailure(body, code, eventBus) +internal fun okhttp3.Response.toFailure(globalErrorReceiver: GlobalErrorReceiver?): Failure { + return toFailure(body, code, globalErrorReceiver) } -private fun toFailure(errorBody: ResponseBody?, httpCode: Int, eventBus: EventBus?): Failure { +private fun toFailure(errorBody: ResponseBody?, httpCode: Int, globalErrorReceiver: GlobalErrorReceiver?): Failure { if (errorBody == null) { return Failure.Unknown(RuntimeException("errorBody should not be null")) } @@ -79,12 +78,12 @@ private fun toFailure(errorBody: ResponseBody?, httpCode: Int, eventBus: EventBu if (matrixError != null) { if (matrixError.code == MatrixError.M_CONSENT_NOT_GIVEN && !matrixError.consentUri.isNullOrBlank()) { - // Also send this error to the bus, for a global management - eventBus?.post(GlobalError.ConsentNotGivenError(matrixError.consentUri)) + // Also send this error to the globalErrorReceiver, for a global management + globalErrorReceiver?.handleGlobalError(GlobalError.ConsentNotGivenError(matrixError.consentUri)) } else if (httpCode == HttpURLConnection.HTTP_UNAUTHORIZED /* 401 */ && matrixError.code == MatrixError.M_UNKNOWN_TOKEN) { - // Also send this error to the bus, for a global management - eventBus?.post(GlobalError.InvalidToken(matrixError.isSoftLogout)) + // Also send this error to the globalErrorReceiver, for a global management + globalErrorReceiver?.handleGlobalError(GlobalError.InvalidToken(matrixError.isSoftLogout)) } return Failure.ServerError(matrixError, httpCode) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index c5f3f65a34..fa07b16c32 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -19,12 +19,7 @@ package org.matrix.android.sdk.internal.session import androidx.annotation.MainThread import dagger.Lazy import io.realm.RealmConfiguration -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import okhttp3.OkHttpClient -import org.greenrobot.eventbus.EventBus -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.failure.GlobalError @@ -65,13 +60,12 @@ import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.di.WorkManagerProvider +import org.matrix.android.sdk.internal.network.GlobalErrorHandler import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.session.sync.job.SyncThread import org.matrix.android.sdk.internal.session.sync.job.SyncWorker -import org.matrix.android.sdk.internal.task.TaskExecutor -import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import org.matrix.android.sdk.internal.util.createUIHandler import timber.log.Timber import javax.inject.Inject @@ -81,7 +75,7 @@ import javax.inject.Provider internal class DefaultSession @Inject constructor( override val sessionParams: SessionParams, private val workManagerProvider: WorkManagerProvider, - private val eventBus: EventBus, + private val globalErrorHandler: GlobalErrorHandler, @SessionId override val sessionId: String, @SessionDatabase private val realmConfiguration: RealmConfiguration, @@ -117,10 +111,8 @@ internal class DefaultSession @Inject constructor( private val accountDataService: Lazy, private val _sharedSecretStorageService: Lazy, private val accountService: Lazy, - private val coroutineDispatchers: MatrixCoroutineDispatchers, private val defaultIdentityService: DefaultIdentityService, private val integrationManagerService: IntegrationManagerService, - private val taskExecutor: TaskExecutor, private val callSignalingService: Lazy, @UnauthenticatedWithCertificate private val unauthenticatedWithCertificateOkHttpClient: Lazy, @@ -140,7 +132,8 @@ internal class DefaultSession @Inject constructor( HomeServerCapabilitiesService by homeServerCapabilitiesService.get(), ProfileService by profileService.get(), AccountDataService by accountDataService.get(), - AccountService by accountService.get() { + AccountService by accountService.get(), + GlobalErrorHandler.Listener { override val sharedSecretStorageService: SharedSecretStorageService get() = _sharedSecretStorageService.get() @@ -162,7 +155,7 @@ internal class DefaultSession @Inject constructor( uiHandler.post { lifecycleObservers.forEach { it.onStart() } } - eventBus.register(this) + globalErrorHandler.listener = this eventSenderProcessor.start() } @@ -206,7 +199,7 @@ internal class DefaultSession @Inject constructor( } cryptoService.get().close() isOpen = false - eventBus.unregister(this) + globalErrorHandler.listener = null eventSenderProcessor.interrupt() } @@ -234,16 +227,7 @@ internal class DefaultSession @Inject constructor( workManagerProvider.cancelAllWorks() } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onGlobalError(globalError: GlobalError) { - if (globalError is GlobalError.InvalidToken - && globalError.softLogout) { - // Mark the token has invalid - taskExecutor.executorScope.launch(Dispatchers.IO) { - sessionParamsStore.setTokenInvalid(sessionId) - } - } - + override fun onGlobalError(globalError: GlobalError) { sessionListeners.dispatchGlobalError(globalError) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt index 659fcc8f5c..f5eade1704 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt @@ -27,7 +27,6 @@ import org.matrix.android.sdk.internal.crypto.SendGossipWorker import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker import org.matrix.android.sdk.internal.crypto.verification.SendVerificationMessageWorker import org.matrix.android.sdk.internal.di.MatrixComponent -import org.matrix.android.sdk.internal.di.SessionAssistedInjectModule import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker import org.matrix.android.sdk.internal.session.account.AccountModule import org.matrix.android.sdk.internal.session.cache.CacheModule @@ -86,7 +85,6 @@ import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers TermsModule::class, AccountDataModule::class, ProfileModule::class, - SessionAssistedInjectModule::class, AccountModule::class, CallModule::class, SearchModule::class diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt index 96b44917bd..468c193ad3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt @@ -26,7 +26,6 @@ import dagger.Provides import dagger.multibindings.IntoSet import io.realm.RealmConfiguration import okhttp3.OkHttpClient -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig @@ -61,9 +60,10 @@ import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificateWithProgress import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserMd5 -import org.matrix.android.sdk.internal.eventbus.EventBusTimberLogger import org.matrix.android.sdk.internal.network.DefaultNetworkConnectivityChecker import org.matrix.android.sdk.internal.network.FallbackNetworkCallbackStrategy +import org.matrix.android.sdk.internal.network.GlobalErrorHandler +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.NetworkCallbackStrategy import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker import org.matrix.android.sdk.internal.network.PreferredNetworkCallbackStrategy @@ -256,16 +256,6 @@ internal abstract class SessionModule { .create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUri.toString()) } - @JvmStatic - @Provides - @SessionScope - fun providesEventBus(): EventBus { - return EventBus - .builder() - .logger(EventBusTimberLogger()) - .build() - } - @JvmStatic @Provides @SessionScope @@ -294,6 +284,9 @@ internal abstract class SessionModule { @Binds abstract fun bindSession(session: DefaultSession): Session + @Binds + abstract fun bindGlobalErrorReceiver(handler: GlobalErrorHandler): GlobalErrorReceiver + @Binds abstract fun bindNetworkConnectivityChecker(checker: DefaultNetworkConnectivityChecker): NetworkConnectivityChecker diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/ChangePasswordTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/ChangePasswordTask.kt index 869d3f516c..1f043b0a9d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/ChangePasswordTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/ChangePasswordTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.account import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface ChangePasswordTask : Task { @@ -32,14 +32,14 @@ internal interface ChangePasswordTask : Task { internal class DefaultChangePasswordTask @Inject constructor( private val accountAPI: AccountAPI, - private val eventBus: EventBus, + private val globalErrorReceiver: GlobalErrorReceiver, @UserId private val userId: String ) : ChangePasswordTask { override suspend fun execute(params: ChangePasswordTask.Params) { val changePasswordParams = ChangePasswordParams.create(userId, params.password, params.newPassword) try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = accountAPI.changePassword(changePasswordParams) } } catch (throwable: Throwable) { @@ -49,7 +49,7 @@ internal class DefaultChangePasswordTask @Inject constructor( /* Avoid infinite loop */ && changePasswordParams.auth?.session == null) { // Retry with authentication - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = accountAPI.changePassword( changePasswordParams.copy(auth = changePasswordParams.auth?.copy(session = registrationFlowResponse.session)) ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt index ac5febcdae..9fb1cbb7d7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.internal.session.account import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.cleanup.CleanupSession import org.matrix.android.sdk.internal.session.identity.IdentityDisconnectTask import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import timber.log.Timber import javax.inject.Inject @@ -34,7 +34,7 @@ internal interface DeactivateAccountTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = accountAPI.deactivate(deactivateAccountParams) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt index 1cedee3374..b21ec1113a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.session.call import org.matrix.android.sdk.api.session.call.TurnServerResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal abstract class GetTurnServerTask : Task { @@ -27,10 +27,10 @@ internal abstract class GetTurnServerTask : Task if (!response.isSuccessful) { - throw response.toFailure(eventBus) + throw response.toFailure(globalErrorReceiver) } else { response.body?.source()?.let { responseAdapter.fromJson(it) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt index 69ced92fe5..da747934e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.filter import org.matrix.android.sdk.api.session.sync.FilterService import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject /** @@ -37,7 +37,7 @@ internal class DefaultSaveFilterTask @Inject constructor( @UserId private val userId: String, private val filterAPI: FilterApi, private val filterRepository: FilterRepository, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SaveFilterTask { override suspend fun execute(params: SaveFilterTask.Params) { @@ -59,7 +59,7 @@ internal class DefaultSaveFilterTask @Inject constructor( } val updated = filterRepository.storeFilter(filterBody, roomFilter) if (updated) { - val filterResponse = executeRequest(eventBus) { + val filterResponse = executeRequest(globalErrorReceiver) { // TODO auto retry apiCall = filterAPI.uploadFilter(userId, filterBody) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt index dd703a5e93..9836164aec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataTask.kt @@ -23,13 +23,13 @@ import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.group.model.GroupRooms import org.matrix.android.sdk.internal.session.group.model.GroupSummaryResponse import org.matrix.android.sdk.internal.session.group.model.GroupUsers import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction -import org.greenrobot.eventbus.EventBus import timber.log.Timber import javax.inject.Inject @@ -43,7 +43,7 @@ internal interface GetGroupDataTask : Task { internal class DefaultGetGroupDataTask @Inject constructor( private val groupAPI: GroupAPI, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetGroupDataTask { private data class GroupData( @@ -64,13 +64,13 @@ internal class DefaultGetGroupDataTask @Inject constructor( } Timber.v("Fetch data for group with ids: ${groupIds.joinToString(";")}") val data = groupIds.map { groupId -> - val groupSummary = executeRequest(eventBus) { + val groupSummary = executeRequest(globalErrorReceiver) { apiCall = groupAPI.getSummary(groupId) } - val groupRooms = executeRequest(eventBus) { + val groupRooms = executeRequest(globalErrorReceiver) { apiCall = groupAPI.getRooms(groupId) } - val groupUsers = executeRequest(eventBus) { + val groupUsers = executeRequest(globalErrorReceiver) { apiCall = groupAPI.getUsers(groupId) } GroupData(groupId, groupSummary, groupRooms, groupUsers) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index f3686b02d3..845cfb392e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.session.homeserver import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.wellknown.WellknownResult import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities @@ -27,6 +26,7 @@ import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEnti import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerConfigExtractor import org.matrix.android.sdk.internal.session.media.GetMediaConfigResult @@ -44,7 +44,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( private val capabilitiesAPI: CapabilitiesAPI, private val mediaAPI: MediaAPI, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus, + private val globalErrorReceiver: GlobalErrorReceiver, private val getWellknownTask: GetWellknownTask, private val configExtractor: IntegrationManagerConfigExtractor, private val homeServerConnectionConfig: HomeServerConnectionConfig, @@ -65,13 +65,13 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( } val capabilities = runCatching { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = capabilitiesAPI.getCapabilities() } }.getOrNull() val mediaConfig = runCatching { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = mediaAPI.getMediaConfig() } }.getOrNull() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt index 69cdfa8faa..a218f3f93c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.session.media import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.cache.CacheStrategy import org.matrix.android.sdk.api.session.media.PreviewUrlData import org.matrix.android.sdk.api.util.JsonDict @@ -25,6 +24,7 @@ import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntity import org.matrix.android.sdk.internal.database.query.get import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction @@ -41,7 +41,7 @@ internal interface GetPreviewUrlTask : Task(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = mediaAPI.getPreviewUrlData(url, timestamp) } .toPreviewUrlData(url) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt index 6c5dad2422..32305cd4e4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.session.media -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject @@ -31,11 +31,11 @@ internal interface GetRawPreviewUrlTask : Task @@ -27,10 +27,10 @@ internal interface GetOpenIdTokenTask : Task internal class DefaultGetOpenIdTokenTask @Inject constructor( @UserId private val userId: String, private val openIdAPI: OpenIdAPI, - private val eventBus: EventBus) : GetOpenIdTokenTask { + private val globalErrorReceiver: GlobalErrorReceiver) : GetOpenIdTokenTask { override suspend fun execute(params: Unit): RequestOpenIdTokenResponse { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = openIdAPI.openIdToken(userId) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt index 2e8a0b3884..6d6d70bb0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.profile import com.google.i18n.phonenumbers.PhoneNumberUtil import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction @@ -37,7 +37,7 @@ internal class DefaultAddThreePidTask @Inject constructor( private val profileAPI: ProfileAPI, @SessionDatabase private val monarchy: Monarchy, private val pendingThreePidMapper: PendingThreePidMapper, - private val eventBus: EventBus) : AddThreePidTask() { + private val globalErrorReceiver: GlobalErrorReceiver) : AddThreePidTask() { override suspend fun execute(params: Params) { when (params.threePid) { @@ -50,7 +50,7 @@ internal class DefaultAddThreePidTask @Inject constructor( val clientSecret = UUID.randomUUID().toString() val sendAttempt = 1 - val result = executeRequest(eventBus) { + val result = executeRequest(globalErrorReceiver) { val body = AddEmailBody( clientSecret = clientSecret, email = threePid.email, @@ -84,7 +84,7 @@ internal class DefaultAddThreePidTask @Inject constructor( val countryCode = parsedNumber.countryCode val country = phoneNumberUtil.getRegionCodeForCountryCode(countryCode) - val result = executeRequest(eventBus) { + val result = executeRequest(globalErrorReceiver) { val body = AddMsisdnBody( clientSecret = clientSecret, country = country, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt index dbe6bff508..a37e5380bc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt @@ -19,12 +19,12 @@ package org.matrix.android.sdk.internal.session.profile import org.matrix.android.sdk.api.session.identity.IdentityServiceError import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.internal.di.AuthenticatedIdentity +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.token.AccessTokenProvider import org.matrix.android.sdk.internal.session.identity.data.IdentityStore import org.matrix.android.sdk.internal.session.identity.data.getIdentityServerUrlWithoutProtocol import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal abstract class BindThreePidsTask : Task { @@ -37,13 +37,13 @@ internal class DefaultBindThreePidsTask @Inject constructor(private val profileA private val identityStore: IdentityStore, @AuthenticatedIdentity private val accessTokenProvider: AccessTokenProvider, - private val eventBus: EventBus) : BindThreePidsTask() { + private val globalErrorReceiver: GlobalErrorReceiver) : BindThreePidsTask() { override suspend fun execute(params: Params) { val identityServerUrlWithoutProtocol = identityStore.getIdentityServerUrlWithoutProtocol() ?: throw IdentityServiceError.NoIdentityServerConfigured val identityServerAccessToken = accessTokenProvider.getToken() ?: throw IdentityServiceError.NoIdentityServerConfigured val identityPendingBinding = identityStore.getPendingBinding(params.threePid) ?: throw IdentityServiceError.NoCurrentBindingError - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = profileAPI.bindThreePid( BindThreePidBody( clientSecret = identityPendingBinding.clientSecret, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt index 3f43cbe599..3549f3613f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.session.profile -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.toMedium +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject @@ -31,10 +31,10 @@ internal abstract class DeleteThreePidTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { val body = DeleteThreePidBody( medium = params.threePid.toMedium(), address = params.threePid.value diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt index 0b1bf88280..1e3a2cb501 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.session.profile import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.api.session.identity.ThreePid @@ -26,6 +25,7 @@ import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction @@ -45,7 +45,7 @@ internal class DefaultFinalizeAddingThreePidTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val pendingThreePidMapper: PendingThreePidMapper, @UserId private val userId: String, - private val eventBus: EventBus) : FinalizeAddingThreePidTask() { + private val globalErrorReceiver: GlobalErrorReceiver) : FinalizeAddingThreePidTask() { override suspend fun execute(params: Params) { if (params.userWantsToCancel.not()) { @@ -58,7 +58,7 @@ internal class DefaultFinalizeAddingThreePidTask @Inject constructor( ?: throw IllegalArgumentException("unknown threepid") try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { val body = FinalizeAddThreePidBody( clientSecret = pendingThreePids.clientSecret, sid = pendingThreePids.sid, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/GetProfileInfoTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/GetProfileInfoTask.kt index 5f1f621ddb..ed60c4a368 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/GetProfileInfoTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/GetProfileInfoTask.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.profile import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal abstract class GetProfileInfoTask : Task { @@ -30,10 +30,10 @@ internal abstract class GetProfileInfoTask : Task internal class DefaultRefreshUserThreePidsTask @Inject constructor(private val profileAPI: ProfileAPI, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus) : RefreshUserThreePidsTask() { + private val globalErrorReceiver: GlobalErrorReceiver) : RefreshUserThreePidsTask() { override suspend fun execute(params: Unit) { - val accountThreePidsResponse = executeRequest(eventBus) { + val accountThreePidsResponse = executeRequest(globalErrorReceiver) { apiCall = profileAPI.getThreePIDs() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetAvatarUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetAvatarUrlTask.kt index 4b863c2098..b29153d665 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetAvatarUrlTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetAvatarUrlTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.session.profile +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal abstract class SetAvatarUrlTask : Task { @@ -30,10 +30,10 @@ internal abstract class SetAvatarUrlTask : Task { internal class DefaultSetAvatarUrlTask @Inject constructor( private val profileAPI: ProfileAPI, - private val eventBus: EventBus) : SetAvatarUrlTask() { + private val globalErrorReceiver: GlobalErrorReceiver) : SetAvatarUrlTask() { override suspend fun execute(params: Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { val body = SetAvatarUrlBody( avatarUrl = params.newAvatarUrl ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetDisplayNameTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetDisplayNameTask.kt index 1fa84f98c1..3f236bc589 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetDisplayNameTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/SetDisplayNameTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.session.profile +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal abstract class SetDisplayNameTask : Task { @@ -30,10 +30,10 @@ internal abstract class SetDisplayNameTask : Task { @@ -34,12 +34,12 @@ internal abstract class UnbindThreePidsTask : Task(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = profileAPI.unbindThreePid( UnbindThreePidBody( identityServerUrlWithoutProtocol, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt index 36804e06fe..efb6c6e836 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt @@ -17,13 +17,13 @@ package org.matrix.android.sdk.internal.session.profile import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.internal.auth.registration.SuccessResult import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject @@ -40,7 +40,7 @@ internal class DefaultValidateSmsCodeTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val pendingThreePidMapper: PendingThreePidMapper, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : ValidateSmsCodeTask { override suspend fun execute(params: ValidateSmsCodeTask.Params) { @@ -58,7 +58,7 @@ internal class DefaultValidateSmsCodeTask @Inject constructor( sid = pendingThreePids.sid, code = params.code ) - val result = executeRequest(eventBus) { + val result = executeRequest(globalErrorReceiver) { apiCall = profileAPI.validateMsisdn(url, body) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt index 31c5cda5ec..d0f7cbfca3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt @@ -19,13 +19,13 @@ import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.pushers.PusherState import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.PusherEntity import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.SessionComponent import org.matrix.android.sdk.internal.util.awaitTransaction @@ -45,7 +45,7 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters) @Inject lateinit var pushersAPI: PushersAPI @Inject @SessionDatabase lateinit var monarchy: Monarchy - @Inject lateinit var eventBus: EventBus + @Inject lateinit var globalErrorReceiver: GlobalErrorReceiver override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -81,7 +81,7 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters) } private suspend fun setPusher(pusher: JsonPusher) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = pushersAPI.setPusher(pusher) } monarchy.awaitTransaction { realm -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt index 28ac5db52e..03748b1528 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.session.pushers import org.matrix.android.sdk.api.pushrules.RuleKind import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface AddPushRuleTask : Task { @@ -31,11 +31,11 @@ internal interface AddPushRuleTask : Task { internal class DefaultAddPushRuleTask @Inject constructor( private val pushRulesApi: PushRulesApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : AddPushRuleTask { override suspend fun execute(params: AddPushRuleTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = pushRulesApi.addRule(params.kind.value, params.pushRule.ruleId, params.pushRule) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt index 0c532cedbc..9fb2d51664 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.session.pushers import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetPushRulesTask : Task { @@ -31,11 +31,11 @@ internal interface GetPushRulesTask : Task { internal class DefaultGetPushRulesTask @Inject constructor( private val pushRulesApi: PushRulesApi, private val savePushRulesTask: SavePushRulesTask, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetPushRulesTask { override suspend fun execute(params: GetPushRulesTask.Params) { - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = pushRulesApi.getAllRules() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushersTask.kt index 39e970f4a8..4c7d370446 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushersTask.kt @@ -20,10 +20,10 @@ import org.matrix.android.sdk.api.session.pushers.PusherState import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.PusherEntity import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetPushersTask : Task @@ -31,11 +31,11 @@ internal interface GetPushersTask : Task internal class DefaultGetPushersTask @Inject constructor( private val pushersAPI: PushersAPI, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetPushersTask { override suspend fun execute(params: Unit) { - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = pushersAPI.getPushers() } monarchy.awaitTransaction { realm -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt index 2fc97cf023..ff3122f566 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.session.pushers import org.matrix.android.sdk.api.pushrules.RuleKind import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface RemovePushRuleTask : Task { @@ -31,11 +31,11 @@ internal interface RemovePushRuleTask : Task { internal class DefaultRemovePushRuleTask @Inject constructor( private val pushRulesApi: PushRulesApi, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : RemovePushRuleTask { override suspend fun execute(params: RemovePushRuleTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = pushRulesApi.deleteRule(params.kind.value, params.pushRule.ruleId) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePusherTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePusherTask.kt index 1f10863799..e3f4fdb789 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePusherTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePusherTask.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import io.realm.Realm -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import javax.inject.Inject internal interface RemovePusherTask : Task { @@ -37,7 +37,7 @@ internal interface RemovePusherTask : Task { internal class DefaultRemovePusherTask @Inject constructor( private val pushersAPI: PushersAPI, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : RemovePusherTask { override suspend fun execute(params: RemovePusherTask.Params) { @@ -62,7 +62,7 @@ internal class DefaultRemovePusherTask @Inject constructor( data = JsonPusherData(existing.data.url, existing.data.format), append = false ) - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = pushersAPI.setPusher(deleteBody) } monarchy.awaitTransaction { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt index c2dca8a9a5..a5c220e662 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.session.pushers import org.matrix.android.sdk.api.pushrules.RuleKind import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface UpdatePushRuleActionsTask : Task { @@ -32,13 +32,13 @@ internal interface UpdatePushRuleActionsTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = pushRulesApi.updateEnableRuleStatus(params.kind.value, params.newPushRule.ruleId, params.newPushRule.enabled) } } @@ -47,7 +47,7 @@ internal class DefaultUpdatePushRuleActionsTask @Inject constructor( // Also ensure the actions are up to date val body = mapOf("actions" to params.newPushRule.actions) - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = pushRulesApi.updateRuleActions(params.kind.value, params.newPushRule.ruleId, body) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt index 4100071c90..f36b5c55fb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.session.pushers import org.matrix.android.sdk.api.pushrules.RuleKind import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface UpdatePushRuleEnableStatusTask : Task { @@ -30,11 +30,11 @@ internal interface UpdatePushRuleEnableStatusTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = directoryAPI.addRoomAlias( roomAlias = params.aliasLocalPart.toFullLocalAlias(userId), body = AddRoomAliasBody( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DefaultAliasService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DefaultAliasService.kt index b6c69224e6..8f58094a2a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DefaultAliasService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DefaultAliasService.kt @@ -16,8 +16,9 @@ package org.matrix.android.sdk.internal.session.room.alias -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.session.room.alias.AliasService internal class DefaultAliasService @AssistedInject constructor( @@ -26,9 +27,9 @@ internal class DefaultAliasService @AssistedInject constructor( private val addRoomAliasTask: AddRoomAliasTask ) : AliasService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): AliasService + fun create(roomId: String): DefaultAliasService } override suspend fun getRoomAliases(): List { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DeleteRoomAliasTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DeleteRoomAliasTask.kt index 3400fd994c..6ad3db90a9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DeleteRoomAliasTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/DeleteRoomAliasTask.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.session.room.alias -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.directory.DirectoryAPI import org.matrix.android.sdk.internal.task.Task @@ -30,11 +30,11 @@ internal interface DeleteRoomAliasTask : Task internal class DefaultDeleteRoomAliasTask @Inject constructor( private val directoryAPI: DirectoryAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : DeleteRoomAliasTask { override suspend fun execute(params: DeleteRoomAliasTask.Params) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = directoryAPI.deleteRoomAlias( roomAlias = params.roomAlias ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt index 543d605707..a53ffc4fcd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt @@ -18,12 +18,12 @@ package org.matrix.android.sdk.internal.session.room.alias import com.zhuinden.monarchy.Monarchy import io.realm.Realm -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.query.findByAlias import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.directory.DirectoryAPI import org.matrix.android.sdk.internal.task.Task @@ -39,7 +39,7 @@ internal interface GetRoomIdByAliasTask : Task { @@ -52,7 +52,7 @@ internal class DefaultGetRoomIdByAliasTask @Inject constructor( Optional.from(null) } else { val description = tryOrNull("## Failed to get roomId from alias") { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = directoryAPI.getRoomIdByAlias(params.roomAlias) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomLocalAliasesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomLocalAliasesTask.kt index 7cfce4ecdc..202cb1f6de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomLocalAliasesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomLocalAliasesTask.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.session.room.alias -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task @@ -30,12 +30,12 @@ internal interface GetRoomLocalAliasesTask : Task { // We do not check for "org.matrix.msc2432", so the API may be missing - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = roomAPI.getAliases(roomId = params.roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasAvailabilityChecker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasAvailabilityChecker.kt index 25ba493891..51a849a35e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasAvailabilityChecker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasAvailabilityChecker.kt @@ -16,10 +16,10 @@ package org.matrix.android.sdk.internal.session.room.alias -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.directory.DirectoryAPI import javax.inject.Inject @@ -27,7 +27,7 @@ import javax.inject.Inject internal class RoomAliasAvailabilityChecker @Inject constructor( @UserId private val userId: String, private val directoryAPI: DirectoryAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) { /** * @param aliasLocalPart the local part of the alias. @@ -41,7 +41,7 @@ internal class RoomAliasAvailabilityChecker @Inject constructor( // Check alias availability val fullAlias = aliasLocalPart.toFullLocalAlias(userId) try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = directoryAPI.getRoomIdByAlias(fullAlias) } } catch (throwable: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/call/DefaultRoomCallService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/call/DefaultRoomCallService.kt index 205a085df6..9bde5054f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/call/DefaultRoomCallService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/call/DefaultRoomCallService.kt @@ -16,8 +16,9 @@ package org.matrix.android.sdk.internal.session.room.call -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.internal.session.room.RoomGetter @@ -27,9 +28,9 @@ internal class DefaultRoomCallService @AssistedInject constructor( private val roomGetter: RoomGetter ) : RoomCallService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): RoomCallService + fun create(roomId: String): DefaultRoomCallService } override fun canStartCall(): Boolean { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt index ef792ab98e..9c16bd1b0f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.room.create import com.zhuinden.monarchy.Monarchy import io.realm.RealmConfiguration import kotlinx.coroutines.TimeoutCancellationException -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.room.alias.RoomAliasError @@ -32,6 +31,7 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker @@ -55,7 +55,7 @@ internal class DefaultCreateRoomTask @Inject constructor( @SessionDatabase private val realmConfiguration: RealmConfiguration, private val createRoomBodyBuilder: CreateRoomBodyBuilder, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : CreateRoomTask { override suspend fun execute(params: CreateRoomParams): String { @@ -75,7 +75,7 @@ internal class DefaultCreateRoomTask @Inject constructor( val createRoomBody = createRoomBodyBuilder.build(params) val createRoomResponse = try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.createRoom(createRoomBody) } } catch (throwable: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetPublicRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetPublicRoomTask.kt index f2bd0c5f69..edd8ae9b0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetPublicRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetPublicRoomTask.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.internal.session.room.directory import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetPublicRoomTask : Task { @@ -33,11 +33,11 @@ internal interface GetPublicRoomTask : Task(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = directoryAPI.getRoomDirectoryVisibility(params.roomId) } .visibility diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetThirdPartyProtocolsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetThirdPartyProtocolsTask.kt index 5e08284706..3477aa671e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetThirdPartyProtocolsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/GetThirdPartyProtocolsTask.kt @@ -17,21 +17,21 @@ package org.matrix.android.sdk.internal.session.room.directory import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetThirdPartyProtocolsTask : Task> internal class DefaultGetThirdPartyProtocolsTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetThirdPartyProtocolsTask { override suspend fun execute(params: Unit): Map { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomAPI.thirdPartyProtocols() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/SetRoomDirectoryVisibilityTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/SetRoomDirectoryVisibilityTask.kt index 33b12aa1ca..cbb0b6d5d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/SetRoomDirectoryVisibilityTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/directory/SetRoomDirectoryVisibilityTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.session.room.directory -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.directory.DirectoryAPI import org.matrix.android.sdk.internal.session.directory.RoomDirectoryVisibilityJson @@ -33,11 +33,11 @@ internal interface SetRoomDirectoryVisibilityTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = directoryAPI.setRoomDirectoryVisibility( params.roomId, RoomDirectoryVisibilityJson(visibility = params.roomDirectoryVisibility) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DefaultDraftService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DefaultDraftService.kt index 93fbfb4df0..1d4ab6d516 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DefaultDraftService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DefaultDraftService.kt @@ -17,8 +17,9 @@ package org.matrix.android.sdk.internal.session.room.draft import androidx.lifecycle.LiveData -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.session.room.send.DraftService import org.matrix.android.sdk.api.session.room.send.UserDraft @@ -30,9 +31,9 @@ internal class DefaultDraftService @AssistedInject constructor(@Assisted private private val coroutineDispatchers: MatrixCoroutineDispatchers ) : DraftService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): DraftService + fun create(roomId: String): DefaultDraftService } /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt index 4fc865304b..cd1c9bbbdd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt @@ -17,8 +17,9 @@ package org.matrix.android.sdk.internal.session.room.membership import androidx.lifecycle.LiveData -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.identity.ThreePid @@ -58,9 +59,9 @@ internal class DefaultMembershipService @AssistedInject constructor( private val userId: String ) : MembershipService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): MembershipService + fun create(roomId: String): DefaultMembershipService } override fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback): Cancelable { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt index 627f927ad8..2be90bf8e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt @@ -17,25 +17,30 @@ package org.matrix.android.sdk.internal.session.room.membership import com.zhuinden.monarchy.Monarchy +import io.realm.Realm +import io.realm.kotlin.createObject +import kotlinx.coroutines.TimeoutCancellationException import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.internal.database.awaitNotEmptyResult import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.database.model.RoomEntity +import org.matrix.android.sdk.internal.database.model.RoomEntityFields +import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction -import io.realm.Realm -import io.realm.kotlin.createObject -import org.greenrobot.eventbus.EventBus +import java.util.concurrent.TimeUnit import javax.inject.Inject internal interface LoadRoomMembersTask : Task { @@ -52,17 +57,44 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( private val syncTokenStore: SyncTokenStore, private val roomSummaryUpdater: RoomSummaryUpdater, private val roomMemberEventHandler: RoomMemberEventHandler, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : LoadRoomMembersTask { override suspend fun execute(params: LoadRoomMembersTask.Params) { - if (areAllMembersAlreadyLoaded(params.roomId)) { - return + when (getRoomMembersLoadStatus(params.roomId)) { + RoomMembersLoadStatusType.NONE -> doRequest(params) + RoomMembersLoadStatusType.LOADING -> waitPreviousRequestToFinish(params) + RoomMembersLoadStatusType.LOADED -> Unit } + } + + private suspend fun waitPreviousRequestToFinish(params: LoadRoomMembersTask.Params) { + try { + awaitNotEmptyResult(monarchy.realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm -> + realm.where(RoomEntity::class.java) + .equalTo(RoomEntityFields.ROOM_ID, params.roomId) + .equalTo(RoomEntityFields.MEMBERS_LOAD_STATUS_STR, RoomMembersLoadStatusType.LOADED.name) + } + } catch (exception: TimeoutCancellationException) { + // Timeout, do the request anyway (?) + doRequest(params) + } + } + + private suspend fun doRequest(params: LoadRoomMembersTask.Params) { + setRoomMembersLoadStatus(params.roomId, RoomMembersLoadStatusType.LOADING) + val lastToken = syncTokenStore.getLastToken() - val response = executeRequest(eventBus) { - apiCall = roomAPI.getMembers(params.roomId, lastToken, null, params.excludeMembership?.value) + val response = try { + executeRequest(globalErrorReceiver) { + apiCall = roomAPI.getMembers(params.roomId, lastToken, null, params.excludeMembership?.value) + } + } catch (throwable: Throwable) { + // Revert status to NONE + setRoomMembersLoadStatus(params.roomId, RoomMembersLoadStatusType.NONE) + throw throwable } + // This will also set the status to LOADED insertInDb(response, params.roomId) } @@ -84,14 +116,23 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( } roomMemberEventHandler.handle(realm, roomId, roomMemberEvent) } - roomEntity.areAllMembersLoaded = true + roomEntity.membersLoadStatus = RoomMembersLoadStatusType.LOADED roomSummaryUpdater.update(realm, roomId, updateMembers = true) } } - private fun areAllMembersAlreadyLoaded(roomId: String): Boolean { - return Realm.getInstance(monarchy.realmConfiguration).use { - RoomEntity.where(it, roomId).findFirst()?.areAllMembersLoaded ?: false + private fun getRoomMembersLoadStatus(roomId: String): RoomMembersLoadStatusType { + var result: RoomMembersLoadStatusType? + Realm.getInstance(monarchy.realmConfiguration).use { + result = RoomEntity.where(it, roomId).findFirst()?.membersLoadStatus + } + return result ?: RoomMembersLoadStatusType.NONE + } + + private suspend fun setRoomMembersLoadStatus(roomId: String, status: RoomMembersLoadStatusType) { + monarchy.awaitTransaction { realm -> + val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) + roomEntity.membersLoadStatus = status } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteTask.kt index 854a332679..05503bd643 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteTask.kt @@ -16,10 +16,10 @@ package org.matrix.android.sdk.internal.session.room.membership.joining +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface InviteTask : Task { @@ -32,11 +32,11 @@ internal interface InviteTask : Task { internal class DefaultInviteTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : InviteTask { override suspend fun execute(params: InviteTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { val body = InviteBody(params.userId, params.reason) apiCall = roomAPI.invite(params.roomId, body) isRetryable = true diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt index dd1dc5fa8a..3b7639d42f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt @@ -30,7 +30,7 @@ import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask import org.matrix.android.sdk.internal.task.Task import io.realm.RealmConfiguration import kotlinx.coroutines.TimeoutCancellationException -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -48,14 +48,18 @@ internal class DefaultJoinRoomTask @Inject constructor( @SessionDatabase private val realmConfiguration: RealmConfiguration, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : JoinRoomTask { override suspend fun execute(params: JoinRoomTask.Params) { roomChangeMembershipStateDataSource.updateState(params.roomIdOrAlias, ChangeMembershipState.Joining) val joinRoomResponse = try { - executeRequest(eventBus) { - apiCall = roomAPI.join(params.roomIdOrAlias, params.viaServers, mapOf("reason" to params.reason)) + executeRequest(globalErrorReceiver) { + apiCall = roomAPI.join( + roomIdOrAlias = params.roomIdOrAlias, + viaServers = params.viaServers.take(3), + params = mapOf("reason" to params.reason) + ) } } catch (failure: Throwable) { roomChangeMembershipStateDataSource.updateState(params.roomIdOrAlias, ChangeMembershipState.FailedJoining(failure)) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/leaving/LeaveRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/leaving/LeaveRoomTask.kt index 58e34a15ec..37bb7570d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/leaving/LeaveRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/leaving/LeaveRoomTask.kt @@ -21,13 +21,13 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import timber.log.Timber import javax.inject.Inject @@ -40,7 +40,7 @@ internal interface LeaveRoomTask : Task { internal class DefaultLeaveRoomTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus, + private val globalErrorReceiver: GlobalErrorReceiver, private val stateEventDataSource: StateEventDataSource, private val roomSummaryDataSource: RoomSummaryDataSource, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource @@ -68,7 +68,7 @@ internal class DefaultLeaveRoomTask @Inject constructor( leaveRoom(predecessorRoomId, reason) } try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.leave(roomId, mapOf("reason" to reason)) } } catch (failure: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt index 80af00fc78..d237ec795e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt @@ -16,11 +16,11 @@ package org.matrix.android.sdk.internal.session.room.membership.threepid -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.identity.IdentityServiceError import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.toMedium import org.matrix.android.sdk.internal.di.AuthenticatedIdentity +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.token.AccessTokenProvider import org.matrix.android.sdk.internal.session.identity.EnsureIdentityTokenTask @@ -39,7 +39,7 @@ internal interface InviteThreePidTask : Task { internal class DefaultInviteThreePidTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus, + private val globalErrorReceiver: GlobalErrorReceiver, private val identityStore: IdentityStore, private val ensureIdentityTokenTask: EnsureIdentityTokenTask, @AuthenticatedIdentity @@ -52,7 +52,7 @@ internal class DefaultInviteThreePidTask @Inject constructor( val identityServerUrlWithoutProtocol = identityStore.getIdentityServerUrlWithoutProtocol() ?: throw IdentityServiceError.NoIdentityServerConfigured val identityServerAccessToken = accessTokenProvider.getToken() ?: throw IdentityServiceError.NoIdentityServerConfigured - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { val body = ThreePidInviteBody( idServer = identityServerUrlWithoutProtocol, idAccessToken = identityServerAccessToken, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt index 67ae55c066..5486d96e28 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt @@ -18,8 +18,9 @@ package org.matrix.android.sdk.internal.session.room.notification import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.pushrules.RuleScope import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState @@ -33,9 +34,9 @@ internal class DefaultRoomPushRuleService @AssistedInject constructor(@Assisted @SessionDatabase private val monarchy: Monarchy) : RoomPushRuleService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): RoomPushRuleService + fun create(roomId: String): DefaultRoomPushRuleService } override fun getLiveRoomNotificationState(): LiveData { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/peeking/ResolveRoomStateTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/peeking/ResolveRoomStateTask.kt index 03ea2408f0..dbec6b555c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/peeking/ResolveRoomStateTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/peeking/ResolveRoomStateTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.session.room.peeking -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task @@ -31,11 +31,11 @@ internal interface ResolveRoomStateTask : Task { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomAPI.getRoomState(params.roomId) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt index 025bea09f4..3cf8cfe5ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt @@ -18,8 +18,9 @@ package org.matrix.android.sdk.internal.session.room.read import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.room.model.ReadReceipt @@ -46,9 +47,9 @@ internal class DefaultReadService @AssistedInject constructor( @UserId private val userId: String ) : ReadService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): ReadService + fun create(roomId: String): DefaultReadService } override fun markAsRead(params: ReadService.MarkAsReadParams, callback: MatrixCallback) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt index a98bb02c83..c7f962a699 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt @@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.session.sync.RoomFullyReadHandler import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import io.realm.Realm -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import timber.log.Timber import javax.inject.Inject import kotlin.collections.set @@ -58,7 +58,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor( private val roomFullyReadHandler: RoomFullyReadHandler, private val readReceiptHandler: ReadReceiptHandler, @UserId private val userId: String, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SetReadMarkersTask { override suspend fun execute(params: SetReadMarkersTask.Params) { @@ -96,7 +96,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor( updateDatabase(params.roomId, markers, shouldUpdateRoomSummary) } if (markers.isNotEmpty()) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { isRetryable = true apiCall = roomAPI.sendReadMarker(params.roomId, markers) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt index a7f3f83980..b27cbbb0b2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt @@ -17,8 +17,9 @@ package org.matrix.android.sdk.internal.session.room.relation import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.events.model.Event @@ -56,9 +57,9 @@ internal class DefaultRelationService @AssistedInject constructor( private val taskExecutor: TaskExecutor) : RelationService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): RelationService + fun create(roomId: String): DefaultRelationService } override fun sendReaction(targetEventId: String, reaction: String): Cancelable { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/FetchEditHistoryTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/FetchEditHistoryTask.kt index 51eecb8c2a..99d02b50da 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/FetchEditHistoryTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/FetchEditHistoryTask.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.internal.session.room.relation import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.RelationType +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface FetchEditHistoryTask : Task> { @@ -35,11 +35,11 @@ internal interface FetchEditHistoryTask : Task { - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = roomAPI.getRelations(params.roomId, params.eventId, RelationType.REPLACE, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt index 25dfe32cbb..c12597bea0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt @@ -18,12 +18,12 @@ package org.matrix.android.sdk.internal.session.room.relation import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent import org.matrix.android.sdk.api.session.room.model.relation.ReactionInfo +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.SessionComponent import org.matrix.android.sdk.internal.session.room.RoomAPI @@ -47,7 +47,7 @@ internal class SendRelationWorker(context: Context, params: WorkerParameters) ) : SessionWorkerParams @Inject lateinit var roomAPI: RoomAPI - @Inject lateinit var eventBus: EventBus + @Inject lateinit var globalErrorReceiver: GlobalErrorReceiver @Inject lateinit var localEchoRepository: LocalEchoRepository override fun injectWith(injector: SessionComponent) { @@ -84,7 +84,7 @@ internal class SendRelationWorker(context: Context, params: WorkerParameters) } private suspend fun sendRelation(roomId: String, relationType: String, relatedEventId: String, localEvent: Event) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.sendRelation( roomId = roomId, parentId = relatedEventId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/DefaultReportingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/DefaultReportingService.kt index cac87a9d30..add17a9fa5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/DefaultReportingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/DefaultReportingService.kt @@ -16,17 +16,18 @@ package org.matrix.android.sdk.internal.session.room.reporting -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.session.room.reporting.ReportingService internal class DefaultReportingService @AssistedInject constructor(@Assisted private val roomId: String, private val reportContentTask: ReportContentTask ) : ReportingService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): ReportingService + fun create(roomId: String): DefaultReportingService } override suspend fun reportContent(eventId: String, score: Int, reason: String) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/ReportContentTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/ReportContentTask.kt index bd11937676..9c6e9907a4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/ReportContentTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/reporting/ReportContentTask.kt @@ -16,10 +16,10 @@ package org.matrix.android.sdk.internal.session.room.reporting +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface ReportContentTask : Task { @@ -33,11 +33,11 @@ internal interface ReportContentTask : Task { internal class DefaultReportContentTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : ReportContentTask { override suspend fun execute(params: ReportContentTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomAPI.reportContent(params.roomId, params.eventId, ReportContentBody(params.score, params.reason)) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt index 8828f3dfed..a12962b51f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt @@ -21,8 +21,9 @@ import androidx.work.BackoffPolicy import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequest import androidx.work.Operation -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.events.model.Event @@ -71,9 +72,9 @@ internal class DefaultSendService @AssistedInject constructor( private val cancelSendTracker: CancelSendTracker ) : SendService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): SendService + fun create(roomId: String): DefaultSendService } private val workerFutureListenerExecutor = Executors.newSingleThreadExecutor() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt index f4871ab35d..f742271fa7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.room.send import com.zhuinden.monarchy.Monarchy import io.realm.Realm -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel @@ -42,7 +41,7 @@ import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater -import org.matrix.android.sdk.internal.session.room.timeline.DefaultTimeline +import org.matrix.android.sdk.internal.session.room.timeline.TimelineInput import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.awaitTransaction import timber.log.Timber @@ -52,7 +51,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private private val taskExecutor: TaskExecutor, private val realmSessionProvider: RealmSessionProvider, private val roomSummaryUpdater: RoomSummaryUpdater, - private val eventBus: EventBus, + private val timelineInput: TimelineInput, private val timelineEventMapper: TimelineEventMapper) { fun createLocalEcho(event: Event) { @@ -76,7 +75,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private } } val timelineEvent = timelineEventMapper.map(timelineEventEntity) - eventBus.post(DefaultTimeline.OnLocalEchoCreated(roomId = roomId, timelineEvent = timelineEvent)) + timelineInput.onLocalEchoCreated(roomId = roomId, timelineEvent = timelineEvent) taskExecutor.executorScope.asyncTransaction(monarchy) { realm -> val eventInsertEntity = EventInsertEntity(event.eventId, event.type).apply { this.insertType = EventInsertType.LOCAL_ECHO @@ -90,7 +89,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private fun updateSendState(eventId: String, roomId: String?, sendState: SendState) { Timber.v("## SendEvent: [${System.currentTimeMillis()}] Update local state of $eventId to ${sendState.name}") - eventBus.post(DefaultTimeline.OnLocalEchoUpdated(roomId ?: "", eventId, sendState)) + timelineInput.onLocalEchoUpdated(roomId = roomId ?: "", eventId = eventId, sendState = sendState) updateEchoAsync(eventId) { realm, sendingEventEntity -> if (sendState == SendState.SENT && sendingEventEntity.sendState == SendState.SYNCED) { // If already synced, do not put as sent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt index 682865eaee..c901c7e18e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt @@ -18,8 +18,8 @@ package org.matrix.android.sdk.internal.session.room.send import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.SessionComponent import org.matrix.android.sdk.internal.session.room.RoomAPI @@ -46,7 +46,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters) ) : SessionWorkerParams @Inject lateinit var roomAPI: RoomAPI - @Inject lateinit var eventBus: EventBus + @Inject lateinit var globalErrorReceiver: GlobalErrorReceiver override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -55,7 +55,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters) override suspend fun doSafeWork(params: Params): Result { val eventId = params.eventId return runCatching { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.redactEvent( params.txID, params.roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt index 37a429d242..c1fc2fd9fe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt @@ -20,7 +20,6 @@ import android.content.Context import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import io.realm.RealmConfiguration -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.failure.shouldBeRetried import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.room.send.SendState @@ -54,7 +53,6 @@ internal class SendEventWorker(context: Context, @Inject lateinit var localEchoRepository: LocalEchoRepository @Inject lateinit var sendEventTask: SendEventTask @Inject lateinit var cryptoService: CryptoService - @Inject lateinit var eventBus: EventBus @Inject lateinit var cancelSendTracker: CancelSendTracker @SessionDatabase @Inject lateinit var realmConfiguration: RealmConfiguration diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt index b546584450..f2640fd1e7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt @@ -18,8 +18,9 @@ package org.matrix.android.sdk.internal.session.room.state import android.net.Uri import androidx.lifecycle.LiveData -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType @@ -35,18 +36,16 @@ import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.session.content.FileUploader -import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasTask internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String, private val stateEventDataSource: StateEventDataSource, private val sendStateTask: SendStateTask, - private val fileUploader: FileUploader, - private val addRoomAliasTask: AddRoomAliasTask + private val fileUploader: FileUploader ) : StateService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): StateService + fun create(roomId: String): DefaultStateService } override fun getStateEvent(eventType: String, stateKey: QueryStringValue): Event? { @@ -74,11 +73,19 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private roomId = roomId, stateKey = stateKey, eventType = eventType, - body = body + body = body.toSafeJson(eventType) ) sendStateTask.execute(params) } + private fun JsonDict.toSafeJson(eventType: String): JsonDict { + // Safe treatment for PowerLevelContent + return when (eventType) { + EventType.STATE_ROOM_POWER_LEVELS -> toSafePowerLevelsContentDict() + else -> this + } + } + override suspend fun updateTopic(topic: String) { sendStateEvent( eventType = EventType.STATE_ROOM_TOPIC, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt new file mode 100644 index 0000000000..a97709e38b --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.state + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.powerlevels.Role +import org.matrix.android.sdk.api.util.JsonDict + +@JsonClass(generateAdapter = true) +internal data class SerializablePowerLevelsContent( + @Json(name = "ban") val ban: Int = Role.Moderator.value, + @Json(name = "kick") val kick: Int = Role.Moderator.value, + @Json(name = "invite") val invite: Int = Role.Moderator.value, + @Json(name = "redact") val redact: Int = Role.Moderator.value, + @Json(name = "events_default") val eventsDefault: Int = Role.Default.value, + @Json(name = "events") val events: Map = emptyMap(), + @Json(name = "users_default") val usersDefault: Int = Role.Default.value, + @Json(name = "users") val users: Map = emptyMap(), + @Json(name = "state_default") val stateDefault: Int = Role.Moderator.value, + // `Int` is the diff here (instead of `Any`) + @Json(name = "notifications") val notifications: Map = emptyMap() +) + +internal fun JsonDict.toSafePowerLevelsContentDict(): JsonDict { + return toModel() + ?.let { content -> + SerializablePowerLevelsContent( + ban = content.ban, + kick = content.kick, + invite = content.invite, + redact = content.redact, + eventsDefault = content.eventsDefault, + events = content.events, + usersDefault = content.usersDefault, + users = content.users, + stateDefault = content.stateDefault, + notifications = content.notifications.mapValues { content.notificationLevel(it.key) } + ) + } + ?.toContent() + ?: emptyMap() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt index 642f68c15b..63691d9207 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt @@ -17,10 +17,10 @@ package org.matrix.android.sdk.internal.session.room.state import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface SendStateTask : Task { @@ -34,11 +34,11 @@ internal interface SendStateTask : Task { internal class DefaultSendStateTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SendStateTask { override suspend fun execute(params: SendStateTask.Params) { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = if (params.stateKey == null) { roomAPI.sendStateEvent( roomId = params.roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/AddTagToRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/AddTagToRoomTask.kt index 013fc86d5c..c3b5c3f78f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/AddTagToRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/AddTagToRoomTask.kt @@ -17,10 +17,10 @@ package org.matrix.android.sdk.internal.session.room.tags import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface AddTagToRoomTask : Task { @@ -35,11 +35,11 @@ internal interface AddTagToRoomTask : Task { internal class DefaultAddTagToRoomTask @Inject constructor( private val roomAPI: RoomAPI, @UserId private val userId: String, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : AddTagToRoomTask { override suspend fun execute(params: AddTagToRoomTask.Params) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.putTag( userId = userId, roomId = params.roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DefaultTagsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DefaultTagsService.kt index d6c02f0a49..02acaa0570 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DefaultTagsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DefaultTagsService.kt @@ -16,8 +16,9 @@ package org.matrix.android.sdk.internal.session.room.tags -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.session.room.tags.TagsService internal class DefaultTagsService @AssistedInject constructor( @@ -26,9 +27,9 @@ internal class DefaultTagsService @AssistedInject constructor( private val deleteTagFromRoomTask: DeleteTagFromRoomTask ) : TagsService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): TagsService + fun create(roomId: String): DefaultTagsService } override suspend fun addTag(tag: String, order: Double?) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DeleteTagFromRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DeleteTagFromRoomTask.kt index b22355d431..d578d21fde 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DeleteTagFromRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/tags/DeleteTagFromRoomTask.kt @@ -17,10 +17,10 @@ package org.matrix.android.sdk.internal.session.room.tags import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface DeleteTagFromRoomTask : Task { @@ -34,11 +34,11 @@ internal interface DeleteTagFromRoomTask : Task(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.deleteTag( userId = userId, roomId = params.roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 86b0497bd0..ae90282d52 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -23,10 +23,8 @@ import io.realm.RealmConfiguration import io.realm.RealmQuery import io.realm.RealmResults import io.realm.Sort -import org.greenrobot.eventbus.EventBus -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode import org.matrix.android.sdk.api.MatrixCallback +import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.EventType @@ -53,6 +51,7 @@ import org.matrix.android.sdk.internal.database.query.filterEvents import org.matrix.android.sdk.internal.database.query.findAllInRoomWithSendStates import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.whereRoomId +import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.util.Debouncer @@ -79,14 +78,13 @@ internal class DefaultTimeline( private val timelineEventMapper: TimelineEventMapper, private val settings: TimelineSettings, private val hiddenReadReceipts: TimelineHiddenReadReceipts, - private val eventBus: EventBus, + private val timelineInput: TimelineInput, private val eventDecryptor: TimelineEventDecryptor, - private val realmSessionProvider: RealmSessionProvider -) : Timeline, TimelineHiddenReadReceipts.Delegate { - - data class OnNewTimelineEvents(val roomId: String, val eventIds: List) - data class OnLocalEchoCreated(val roomId: String, val timelineEvent: TimelineEvent) - data class OnLocalEchoUpdated(val roomId: String, val eventId: String, val sendState: SendState) + private val realmSessionProvider: RealmSessionProvider, + private val loadRoomMembersTask: LoadRoomMembersTask +) : Timeline, + TimelineHiddenReadReceipts.Delegate, + TimelineInput.Listener { companion object { val BACKGROUND_HANDLER = createBackgroundHandler("TIMELINE_DB_THREAD") @@ -158,7 +156,7 @@ internal class DefaultTimeline( override fun start() { if (isStarted.compareAndSet(false, true)) { Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId") - eventBus.register(this) + timelineInput.listeners.add(this) BACKGROUND_HANDLER.post { eventDecryptor.start() val realm = Realm.getInstance(realmConfiguration) @@ -184,6 +182,13 @@ internal class DefaultTimeline( if (settings.shouldHandleHiddenReadReceipts()) { hiddenReadReceipts.start(realm, filteredEvents, nonFilteredEvents, this) } + + loadRoomMembersTask + .configureWith(LoadRoomMembersTask.Params(roomId)) { + this.callback = NoOpMatrixCallback() + } + .executeBy(taskExecutor) + isReady.set(true) } } @@ -196,7 +201,7 @@ internal class DefaultTimeline( override fun dispose() { if (isStarted.compareAndSet(true, false)) { isReady.set(false) - eventBus.unregister(this) + timelineInput.listeners.remove(this) Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId") cancelableBag.cancel() BACKGROUND_HANDLER.removeCallbacksAndMessages(null) @@ -313,25 +318,22 @@ internal class DefaultTimeline( postSnapshot() } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onNewTimelineEvents(onNewTimelineEvents: OnNewTimelineEvents) { - if (isLive && onNewTimelineEvents.roomId == roomId) { + override fun onNewTimelineEvents(roomId: String, eventIds: List) { + if (isLive && this.roomId == roomId) { listeners.forEach { - it.onNewTimelineEvents(onNewTimelineEvents.eventIds) + it.onNewTimelineEvents(eventIds) } } } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onLocalEchoCreated(onLocalEchoCreated: OnLocalEchoCreated) { - if (uiEchoManager.onLocalEchoCreated(onLocalEchoCreated)) { + override fun onLocalEchoCreated(roomId: String, timelineEvent: TimelineEvent) { + if (uiEchoManager.onLocalEchoCreated(roomId, timelineEvent)) { postSnapshot() } } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onLocalEchoUpdated(onLocalEchoUpdated: OnLocalEchoUpdated) { - if (uiEchoManager.onLocalEchoUpdated(onLocalEchoUpdated)) { + override fun onLocalEchoUpdated(roomId: String, eventId: String, sendState: SendState) { + if (uiEchoManager.onLocalEchoUpdated(roomId, eventId, sendState)) { postSnapshot() } } @@ -848,11 +850,11 @@ internal class DefaultTimeline( } } - fun onLocalEchoUpdated(onLocalEchoUpdated: OnLocalEchoUpdated): Boolean { - if (isLive && onLocalEchoUpdated.roomId == roomId) { - val existingState = inMemorySendingStates[onLocalEchoUpdated.eventId] - inMemorySendingStates[onLocalEchoUpdated.eventId] = onLocalEchoUpdated.sendState - if (existingState != onLocalEchoUpdated.sendState) { + fun onLocalEchoUpdated(roomId: String, eventId: String, sendState: SendState): Boolean { + if (isLive && roomId == this@DefaultTimeline.roomId) { + val existingState = inMemorySendingStates[eventId] + inMemorySendingStates[eventId] = sendState + if (existingState != sendState) { return true } } @@ -860,22 +862,22 @@ internal class DefaultTimeline( } // return true if should update - fun onLocalEchoCreated(onLocalEchoCreated: OnLocalEchoCreated): Boolean { + fun onLocalEchoCreated(roomId: String, timelineEvent: TimelineEvent): Boolean { var postSnapshot = false - if (isLive && onLocalEchoCreated.roomId == roomId) { + if (isLive && roomId == this@DefaultTimeline.roomId) { // Manage some ui echos (do it before filter because actual event could be filtered out) - when (onLocalEchoCreated.timelineEvent.root.getClearType()) { + when (timelineEvent.root.getClearType()) { EventType.REDACTION -> { } EventType.REACTION -> { - val content = onLocalEchoCreated.timelineEvent.root.content?.toModel() + val content = timelineEvent.root.content?.toModel() if (RelationType.ANNOTATION == content?.relatesTo?.type) { val reaction = content.relatesTo.key val relatedEventID = content.relatesTo.eventId inMemoryReactions.getOrPut(relatedEventID) { mutableListOf() } .add( ReactionUiEchoData( - localEchoId = onLocalEchoCreated.timelineEvent.eventId, + localEchoId = timelineEvent.eventId, reactedOnEventId = relatedEventID, reaction = reaction ) @@ -888,12 +890,12 @@ internal class DefaultTimeline( } // do not add events that would have been filtered - if (listOf(onLocalEchoCreated.timelineEvent).filterEventsWithSettings().isNotEmpty()) { + if (listOf(timelineEvent).filterEventsWithSettings().isNotEmpty()) { listeners.forEach { - it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId)) + it.onNewTimelineEvents(listOf(timelineEvent.eventId)) } - Timber.v("On local echo created: ${onLocalEchoCreated.timelineEvent.eventId}") - inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent) + Timber.v("On local echo created: ${timelineEvent.eventId}") + inMemorySendingEvents.add(0, timelineEvent) postSnapshot = true } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt index 783aa53ddf..ef890db79e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt @@ -18,12 +18,12 @@ package org.matrix.android.sdk.internal.session.room.timeline import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import com.zhuinden.monarchy.Monarchy import io.realm.Sort import io.realm.kotlin.where -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.events.model.isImageMessage import org.matrix.android.sdk.api.session.events.model.isVideoMessage import org.matrix.android.sdk.api.session.room.timeline.Timeline @@ -39,24 +39,26 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.task.TaskExecutor internal class DefaultTimelineService @AssistedInject constructor(@Assisted private val roomId: String, @SessionDatabase private val monarchy: Monarchy, private val realmSessionProvider: RealmSessionProvider, - private val eventBus: EventBus, + private val timelineInput: TimelineInput, private val taskExecutor: TaskExecutor, private val contextOfEventTask: GetContextOfEventTask, private val eventDecryptor: TimelineEventDecryptor, private val paginationTask: PaginationTask, private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, private val timelineEventMapper: TimelineEventMapper, - private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper + private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper, + private val loadRoomMembersTask: LoadRoomMembersTask ) : TimelineService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): TimelineService + fun create(roomId: String): DefaultTimelineService } override fun createTimeline(eventId: String?, settings: TimelineSettings): Timeline { @@ -70,10 +72,11 @@ internal class DefaultTimelineService @AssistedInject constructor(@Assisted priv timelineEventMapper = timelineEventMapper, settings = settings, hiddenReadReceipts = TimelineHiddenReadReceipts(readReceiptsSummaryMapper, roomId, settings), - eventBus = eventBus, + timelineInput = timelineInput, eventDecryptor = eventDecryptor, fetchTokenAndPaginateTask = fetchTokenAndPaginateTask, - realmSessionProvider = realmSessionProvider + realmSessionProvider = realmSessionProvider, + loadRoomMembersTask = loadRoomMembersTask ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/FetchTokenAndPaginateTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/FetchTokenAndPaginateTask.kt index d1bfa1adcb..76c4b3812c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/FetchTokenAndPaginateTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/FetchTokenAndPaginateTask.kt @@ -20,12 +20,12 @@ import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.internal.database.model.ChunkEntity import org.matrix.android.sdk.internal.database.query.findIncludingEvent import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.filter.FilterRepository import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface FetchTokenAndPaginateTask : Task { @@ -43,12 +43,12 @@ internal class DefaultFetchTokenAndPaginateTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val filterRepository: FilterRepository, private val paginationTask: PaginationTask, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : FetchTokenAndPaginateTask { override suspend fun execute(params: FetchTokenAndPaginateTask.Params): TokenChunkEventPersistor.Result { val filter = filterRepository.getRoomFilter() - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = roomAPI.getContextOfEvent(params.roomId, params.lastKnownEventId, 0, filter) } val fromToken = if (params.direction == PaginationDirection.FORWARDS) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetContextOfEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetContextOfEventTask.kt index 7a611dd350..d02a7bafe9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetContextOfEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetContextOfEventTask.kt @@ -16,11 +16,11 @@ package org.matrix.android.sdk.internal.session.room.timeline +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.filter.FilterRepository import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetContextOfEventTask : Task { @@ -35,12 +35,12 @@ internal class DefaultGetContextOfEventTask @Inject constructor( private val roomAPI: RoomAPI, private val filterRepository: FilterRepository, private val tokenChunkEventPersistor: TokenChunkEventPersistor, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : GetContextOfEventTask { override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result { val filter = filterRepository.getRoomFilter() - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { // We are limiting the response to the event with eventId to be sure we don't have any issue with potential merging process. apiCall = roomAPI.getContextOfEvent(params.roomId, params.eventId, 0, filter) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt index acac3929ae..b8585b1e74 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt @@ -17,17 +17,17 @@ package org.matrix.android.sdk.internal.session.room.timeline import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject // TODO Add parent task internal class GetEventTask @Inject constructor( private val roomAPI: RoomAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : Task { internal data class Params( @@ -36,7 +36,7 @@ internal class GetEventTask @Inject constructor( ) override suspend fun execute(params: Params): Event { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { apiCall = roomAPI.getEvent(params.roomId, params.eventId) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationTask.kt index b663d03bd7..1f99893e17 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationTask.kt @@ -16,11 +16,11 @@ package org.matrix.android.sdk.internal.session.room.timeline +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.filter.FilterRepository import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface PaginationTask : Task { @@ -37,12 +37,12 @@ internal class DefaultPaginationTask @Inject constructor( private val roomAPI: RoomAPI, private val filterRepository: FilterRepository, private val tokenChunkEventPersistor: TokenChunkEventPersistor, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : PaginationTask { override suspend fun execute(params: PaginationTask.Params): TokenChunkEventPersistor.Result { val filter = filterRepository.getRoomFilter() - val chunk = executeRequest(eventBus) { + val chunk = executeRequest(globalErrorReceiver) { isRetryable = true apiCall = roomAPI.getRoomMessagesFrom(params.roomId, params.from, params.direction.value, params.limit, filter) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineInput.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineInput.kt new file mode 100644 index 0000000000..002ab1dd8a --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineInput.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.timeline + +import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent +import org.matrix.android.sdk.internal.session.SessionScope +import javax.inject.Inject + +@SessionScope +internal class TimelineInput @Inject constructor() { + fun onLocalEchoCreated(roomId: String, timelineEvent: TimelineEvent) { + listeners.toSet().forEach { it.onLocalEchoCreated(roomId, timelineEvent) } + } + + fun onLocalEchoUpdated(roomId: String, eventId: String, sendState: SendState) { + listeners.toSet().forEach { it.onLocalEchoUpdated(roomId, eventId, sendState) } + } + + fun onNewTimelineEvents(roomId: String, eventIds: List) { + listeners.toSet().forEach { it.onNewTimelineEvents(roomId, eventIds) } + } + + val listeners = mutableSetOf() + + internal interface Listener { + fun onLocalEchoCreated(roomId: String, timelineEvent: TimelineEvent) + fun onLocalEchoUpdated(roomId: String, eventId: String, sendState: SendState) + fun onNewTimelineEvents(roomId: String, eventIds: List) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt index 5dcf3fcdd6..39b7967bc1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt @@ -17,8 +17,9 @@ package org.matrix.android.sdk.internal.session.room.typing import android.os.SystemClock -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.room.typing.TypingService import org.matrix.android.sdk.api.util.Cancelable @@ -38,9 +39,9 @@ internal class DefaultTypingService @AssistedInject constructor( private val sendTypingTask: SendTypingTask ) : TypingService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): TypingService + fun create(roomId: String): DefaultTypingService } private var currentTask: Cancelable? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt index c8cbb08e2c..3b56d04872 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task import kotlinx.coroutines.delay -import org.greenrobot.eventbus.EventBus +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import javax.inject.Inject internal interface SendTypingTask : Task { @@ -38,13 +38,13 @@ internal interface SendTypingTask : Task { internal class DefaultSendTypingTask @Inject constructor( private val roomAPI: RoomAPI, @UserId private val userId: String, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SendTypingTask { override suspend fun execute(params: SendTypingTask.Params) { delay(params.delay ?: -1) - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.sendTypingState( params.roomId, userId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/DefaultUploadsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/DefaultUploadsService.kt index 895f1cf50d..6d841644dc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/DefaultUploadsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/DefaultUploadsService.kt @@ -16,8 +16,9 @@ package org.matrix.android.sdk.internal.session.room.uploads -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.room.uploads.GetUploadsResult import org.matrix.android.sdk.api.session.room.uploads.UploadsService @@ -28,9 +29,9 @@ internal class DefaultUploadsService @AssistedInject constructor( private val cryptoService: CryptoService ) : UploadsService { - @AssistedInject.Factory + @AssistedFactory interface Factory { - fun create(roomId: String): UploadsService + fun create(roomId: String): DefaultUploadsService } override suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt index d0439ce7f9..0c0e6a8ed0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt @@ -31,6 +31,7 @@ import org.matrix.android.sdk.internal.database.model.EventEntityFields import org.matrix.android.sdk.internal.database.query.TimelineEventFilter import org.matrix.android.sdk.internal.database.query.whereType import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.filter.FilterFactory import org.matrix.android.sdk.internal.session.room.RoomAPI @@ -39,7 +40,6 @@ import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.session.room.timeline.PaginationResponse import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface GetUploadsTask : Task { @@ -56,7 +56,7 @@ internal class DefaultGetUploadsTask @Inject constructor( private val roomAPI: RoomAPI, private val tokenStore: SyncTokenStore, @SessionDatabase private val monarchy: Monarchy, - private val eventBus: EventBus) + private val globalErrorReceiver: GlobalErrorReceiver) : GetUploadsTask { override suspend fun execute(params: GetUploadsTask.Params): GetUploadsResult { @@ -86,7 +86,7 @@ internal class DefaultGetUploadsTask @Inject constructor( val since = params.since ?: tokenStore.getLastToken() ?: throw IllegalStateException("No token available") val filter = FilterFactory.createUploadsFilter(params.numberOfEvents).toJSONString() - val chunk = executeRequest(eventBus) { + val chunk = executeRequest(globalErrorReceiver) { apiCall = roomAPI.getRoomMessagesFrom(params.roomId, since, PaginationDirection.BACKWARDS.value, params.numberOfEvents, filter) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt index 4f574e5ead..402602e4d5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt @@ -16,10 +16,10 @@ package org.matrix.android.sdk.internal.session.search -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.search.EventAndSender import org.matrix.android.sdk.api.session.search.SearchResult import org.matrix.android.sdk.api.util.MatrixItem +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.search.request.SearchRequestBody import org.matrix.android.sdk.internal.session.search.request.SearchRequestCategories @@ -47,11 +47,11 @@ internal interface SearchTask : Task { internal class DefaultSearchTask @Inject constructor( private val searchAPI: SearchAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SearchTask { override suspend fun execute(params: SearchTask.Params): SearchResult { - return executeRequest(eventBus) { + return executeRequest(globalErrorReceiver) { val searchRequestBody = SearchRequestBody( searchCategories = SearchRequestCategories( roomEvents = SearchRequestRoomEvents( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignInAgainTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignInAgainTask.kt index 3bed0bdbff..2c3cd5d270 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignInAgainTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignInAgainTask.kt @@ -20,9 +20,9 @@ import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface SignInAgainTask : Task { @@ -35,11 +35,11 @@ internal class DefaultSignInAgainTask @Inject constructor( private val signOutAPI: SignOutAPI, private val sessionParams: SessionParams, private val sessionParamsStore: SessionParamsStore, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SignInAgainTask { override suspend fun execute(params: SignInAgainTask.Params) { - val newCredentials = executeRequest(eventBus) { + val newCredentials = executeRequest(globalErrorReceiver) { apiCall = signOutAPI.loginAgain( PasswordLoginParams.userIdentifier( // Reuse the same userId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt index 153ea5a6fd..0cb8704782 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt @@ -18,11 +18,11 @@ package org.matrix.android.sdk.internal.session.signout import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.cleanup.CleanupSession import org.matrix.android.sdk.internal.session.identity.IdentityDisconnectTask import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import timber.log.Timber import java.net.HttpURLConnection import javax.inject.Inject @@ -35,7 +35,7 @@ internal interface SignOutTask : Task { internal class DefaultSignOutTask @Inject constructor( private val signOutAPI: SignOutAPI, - private val eventBus: EventBus, + private val globalErrorReceiver: GlobalErrorReceiver, private val identityDisconnectTask: IdentityDisconnectTask, private val cleanupSession: CleanupSession ) : SignOutTask { @@ -45,7 +45,7 @@ internal class DefaultSignOutTask @Inject constructor( if (params.signOutFromHomeserver) { Timber.d("SignOut: send request...") try { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = signOutAPI.signOut() } } catch (throwable: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncHandler.kt index b1b2f65dc2..456b0f9c26 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncHandler.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.sync import io.realm.Realm import io.realm.kotlin.createObject -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.R import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.events.model.Event @@ -55,8 +54,8 @@ import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembers import org.matrix.android.sdk.internal.session.room.membership.RoomMemberEventHandler import org.matrix.android.sdk.internal.session.room.read.FullyReadContent import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater -import org.matrix.android.sdk.internal.session.room.timeline.DefaultTimeline import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection +import org.matrix.android.sdk.internal.session.room.timeline.TimelineInput import org.matrix.android.sdk.internal.session.room.typing.TypingEventContent import org.matrix.android.sdk.internal.session.sync.model.InvitedRoomSync import org.matrix.android.sdk.internal.session.sync.model.RoomSync @@ -75,7 +74,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle private val roomTypingUsersHandler: RoomTypingUsersHandler, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, @UserId private val userId: String, - private val eventBus: EventBus) { + private val timelineInput: TimelineInput) { sealed class HandlingStrategy { data class JOINED(val data: Map) : HandlingStrategy() @@ -348,7 +347,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle } } // posting new events to timeline if any is registered - eventBus.post(DefaultTimeline.OnNewTimelineEvents(roomId = roomId, eventIds = eventIds)) + timelineInput.onNewTimelineEvents(roomId = roomId, eventIds = eventIds) return chunkEntity } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt index b4fd6e7386..7c38230065 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.session.sync -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.R import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.TimeOutInterceptor import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.DefaultInitialSyncProgressService @@ -48,7 +48,7 @@ internal class DefaultSyncTask @Inject constructor( private val getHomeServerCapabilitiesTask: GetHomeServerCapabilitiesTask, private val userStore: UserStore, private val syncTaskSequencer: SyncTaskSequencer, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SyncTask { override suspend fun execute(params: SyncTask.Params) = syncTaskSequencer.post { @@ -81,7 +81,7 @@ internal class DefaultSyncTask @Inject constructor( val readTimeOut = (params.timeout + TIMEOUT_MARGIN).coerceAtLeast(TimeOutInterceptor.DEFAULT_LONG_TIMEOUT) - val syncResponse = executeRequest(eventBus) { + val syncResponse = executeRequest(globalErrorReceiver) { apiCall = syncAPI.sync( params = requestParams, readTimeOut = readTimeOut diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt index 6d100a71f9..cce169c246 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt @@ -36,6 +36,7 @@ import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import timber.log.Timber +import java.net.SocketTimeoutException import java.util.concurrent.atomic.AtomicBoolean /** @@ -49,8 +50,9 @@ abstract class SyncService : Service() { private var sessionId: String? = null private var mIsSelfDestroyed: Boolean = false - private var syncTimeoutSeconds: Int = 6 - private var syncDelaySeconds: Int = 60 + private var syncTimeoutSeconds: Int = getDefaultSyncTimeoutSeconds() + private var syncDelaySeconds: Int = getDefaultSyncDelaySeconds() + private var periodic: Boolean = false private var preventReschedule: Boolean = false @@ -68,14 +70,12 @@ abstract class SyncService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Timber.i("## Sync: onStartCommand [$this] $intent with action: ${intent?.action}") - - // We should start we have to ensure we fulfill contract to show notification - // for foreground service (as per design for this service) - // TODO can we check if it's really in foreground - onStart(isInitialSync) when (intent?.action) { ACTION_STOP -> { Timber.i("## Sync: stop command received") + // We should start we have to ensure we fulfill contract to show notification + // for foreground service (as per design for this service) + onStart(isInitialSync) // If it was periodic we ensure that it will not reschedule itself preventReschedule = true // we don't want to cancel initial syncs, let it finish @@ -85,11 +85,12 @@ abstract class SyncService : Service() { } else -> { val isInit = initialize(intent) + onStart(isInitialSync) if (isInit) { periodic = intent?.getBooleanExtra(EXTRA_PERIODIC, false) ?: false val onNetworkBack = intent?.getBooleanExtra(EXTRA_NETWORK_BACK_RESTART, false) ?: false Timber.d("## Sync: command received, periodic: $periodic networkBack: $onNetworkBack") - if (onNetworkBack && !backgroundDetectionObserver.isInBackground) { + if (!isInitialSync && onNetworkBack && !backgroundDetectionObserver.isInBackground) { // the restart after network occurs while the app is in foreground // so just stop. It will be restarted when entering background preventReschedule = true @@ -119,7 +120,11 @@ abstract class SyncService : Service() { serviceScope.coroutineContext.cancelChildren() if (!preventReschedule && periodic && sessionId != null && backgroundDetectionObserver.isInBackground) { Timber.d("## Sync: Reschedule service in $syncDelaySeconds sec") - onRescheduleAsked(sessionId ?: "", false, syncTimeoutSeconds, syncDelaySeconds) + onRescheduleAsked( + sessionId = sessionId ?: "", + syncTimeoutSeconds = syncTimeoutSeconds, + syncDelaySeconds = syncDelaySeconds + ) } super.onDestroy() } @@ -165,10 +170,23 @@ abstract class SyncService : Service() { preventReschedule = true } if (throwable is Failure.NetworkConnection) { - // Network is off, no need to reschedule endless alarms :/ + // Timeout is not critical, so retry as soon as possible. + if (throwable.cause is SocketTimeoutException) { + // For big accounts, computing sync response can take time, but Synapse will cache the + // result for the next request. So keep retrying in loop + Timber.w("Timeout during sync, retry in loop") + doSync() + return + } + // Network might be off, no need to reschedule endless alarms :/ preventReschedule = true - // Instead start a work to restart background sync when network is back - onNetworkError(sessionId ?: "", isInitialSync, syncTimeoutSeconds, syncDelaySeconds) + // Instead start a work to restart background sync when network is on + onNetworkError( + sessionId = sessionId ?: "", + syncTimeoutSeconds = syncTimeoutSeconds, + syncDelaySeconds = syncDelaySeconds, + isPeriodic = periodic + ) } // JobCancellation could be caught here when onDestroy cancels the coroutine context if (isRunning.get()) stopMe() @@ -182,8 +200,8 @@ abstract class SyncService : Service() { } val matrix = Matrix.getInstance(applicationContext) val safeSessionId = intent.getStringExtra(EXTRA_SESSION_ID) ?: return false - syncTimeoutSeconds = intent.getIntExtra(EXTRA_TIMEOUT_SECONDS, 6) - syncDelaySeconds = intent.getIntExtra(EXTRA_DELAY_SECONDS, 60) + syncTimeoutSeconds = intent.getIntExtra(EXTRA_TIMEOUT_SECONDS, getDefaultSyncTimeoutSeconds()) + syncDelaySeconds = intent.getIntExtra(EXTRA_DELAY_SECONDS, getDefaultSyncDelaySeconds()) try { val sessionComponent = matrix.sessionManager.getSessionComponent(safeSessionId) ?: throw IllegalStateException("## Sync: You should have a session to make it work") @@ -202,11 +220,15 @@ abstract class SyncService : Service() { } } + abstract fun getDefaultSyncTimeoutSeconds(): Int + + abstract fun getDefaultSyncDelaySeconds(): Int + abstract fun onStart(isInitialSync: Boolean) - abstract fun onRescheduleAsked(sessionId: String, isInitialSync: Boolean, timeout: Int, delay: Int) + abstract fun onRescheduleAsked(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int) - abstract fun onNetworkError(sessionId: String, isInitialSync: Boolean, timeout: Int, delay: Int) + abstract fun onNetworkError(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int, isPeriodic: Boolean) override fun onBind(intent: Intent?): IBinder? { return null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt index d1393c8b37..26e8d3380a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.internal.session.user.accountdata import com.zhuinden.monarchy.Monarchy -import org.greenrobot.eventbus.EventBus import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.internal.database.model.IgnoredUserEntity import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.sync.model.accountdata.IgnoredUsersContent import org.matrix.android.sdk.internal.task.Task @@ -40,7 +40,7 @@ internal class DefaultUpdateIgnoredUserIdsTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val saveIgnoredUsersTask: SaveIgnoredUsersTask, @UserId private val userId: String, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : UpdateIgnoredUserIdsTask { override suspend fun execute(params: UpdateIgnoredUserIdsTask.Params) { @@ -63,7 +63,7 @@ internal class DefaultUpdateIgnoredUserIdsTask @Inject constructor( val list = ignoredUserIds.toList() val body = IgnoredUsersContent.createWithUserIds(list) - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = accountDataApi.setAccountData(userId, UserAccountDataTypes.TYPE_IGNORED_USER_LIST, body) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt index 80ab79b228..dba28253a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateUserAccountDataTask.kt @@ -24,8 +24,8 @@ import org.matrix.android.sdk.internal.session.sync.model.accountdata.AcceptedTe import org.matrix.android.sdk.internal.session.sync.model.accountdata.BreadcrumbsContent import org.matrix.android.sdk.internal.session.sync.model.accountdata.IdentityServerContent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface UpdateUserAccountDataTask : Task { @@ -100,11 +100,11 @@ internal interface UpdateUserAccountDataTask : Task> { @@ -34,11 +34,11 @@ internal interface SearchUserTask : Task> { internal class DefaultSearchUserTask @Inject constructor( private val searchUserAPI: SearchUserAPI, - private val eventBus: EventBus + private val globalErrorReceiver: GlobalErrorReceiver ) : SearchUserTask { override suspend fun execute(params: SearchUserTask.Params): List { - val response = executeRequest(eventBus) { + val response = executeRequest(globalErrorReceiver) { apiCall = searchUserAPI.searchUsers(SearchUsersParams(params.search, params.limit)) } return response.users.map { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt index 422615af2d..ae807ce30f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt @@ -25,10 +25,10 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFie import org.matrix.android.sdk.internal.database.query.whereStateKey import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task -import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal interface CreateWidgetTask : Task { @@ -43,10 +43,10 @@ internal interface CreateWidgetTask : Task { internal class DefaultCreateWidgetTask @Inject constructor(@SessionDatabase private val monarchy: Monarchy, private val roomAPI: RoomAPI, @UserId private val userId: String, - private val eventBus: EventBus) : CreateWidgetTask { + private val globalErrorReceiver: GlobalErrorReceiver) : CreateWidgetTask { override suspend fun execute(params: CreateWidgetTask.Params) { - executeRequest(eventBus) { + executeRequest(globalErrorReceiver) { apiCall = roomAPI.sendStateEvent( roomId = params.roomId, stateEventType = EventType.STATE_ROOM_WIDGET_LEGACY, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt index c6647f7572..b58cab99b5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt @@ -20,6 +20,7 @@ import android.content.Context import androidx.work.ListenableWorker import androidx.work.WorkerFactory import androidx.work.WorkerParameters +import timber.log.Timber import javax.inject.Inject import javax.inject.Provider @@ -32,6 +33,8 @@ class MatrixWorkerFactory @Inject constructor( workerClassName: String, workerParameters: WorkerParameters ): ListenableWorker? { + Timber.d("MatrixWorkerFactory.createWorker for $workerClassName") + val foundEntry = workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) } val factoryProvider = foundEntry?.value diff --git a/matrix-sdk-android/src/main/res/values-cs/strings.xml b/matrix-sdk-android/src/main/res/values-cs/strings.xml index 50dea12b09..adb3517927 100644 --- a/matrix-sdk-android/src/main/res/values-cs/strings.xml +++ b/matrix-sdk-android/src/main/res/values-cs/strings.xml @@ -242,4 +242,30 @@ • Server shodující se s %s je zakázán. Nastavili jste ACL serveru pro tuto místnost. %s nastavili ACL serveru pro tuto místnost. + Změnili jste adresy pro tuto místnost. + %1$s změnili adresy pro tuto místnost. + Změnili jste hlavní a alternativní adresu pro tuto místnost. + %1$s změnili hlavní a alternativní adresu pro tuto místnost. + Změnili jste alternativní adresu pro tuto místnost. + %1$s změnili alternativní adresu pro tuto místnost. + + Odstranili jste alternativní adresu %1$s pro tuto místnost. + Odstranili jste alternativní adresy %1$s pro tuto místnost. + Odstranili jste alternativní adresy %1$s pro tuto místnost. + + + %1$s odstranili alternativní adresu %2$s pro tuto místnost. + %1$s odstranili alternativní adresy %2$s pro tuto místnost. + %1$s odstranili alternativní adresy %2$s pro tuto místnost. + + + Přidali jste alternativní adresu %1$s pro tuto místnost. + Přidali jste alternativní adresy %1$s pro tuto místnost. + Přidali jste alternativní adresy %1$s pro tuto místnost. + + + %1$s přidali alternativní adresu %2$s pro tuto místnost. + %1$s přidali alternativní adresy %2$s pro tuto místnost. + %1$s přidali alternativní adresy %2$s pro tuto místnost. + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-et/strings.xml b/matrix-sdk-android/src/main/res/values-et/strings.xml index 957c0b9955..af2cc33b99 100644 --- a/matrix-sdk-android/src/main/res/values-et/strings.xml +++ b/matrix-sdk-android/src/main/res/values-et/strings.xml @@ -47,7 +47,7 @@ Sõnumi saatja seade ei ole selle sõnumi jaoks saatnud dekrüptimisvõtmeid. Ei saanud muuta sõnumit Sõnumi saatmine ei õnnestunud - Faili üles laadimine ei õnnestunud + Pildi üleslaadimine ei õnnestunud Võrguühenduse viga Matrix\'i viga Hetkel ei ole võimalik uuesti liituda tühja jututoaga. @@ -236,4 +236,26 @@ • Lubatud on serverid, mille ip-aadress vastab mustrile. • Lubatud on serverid, mille nimes leidub %s. • Keelatud on serverid, mille nimes leidub %s. + %1$s muutis selle jututoa aadresse. + Sa muutsid selle jututoa põhiaadressi ja täiendavaid aadresse. + %1$s muutis selle jututoa täiendavaid aadresse. + Sa muutsid selle jututoa täiendavaid aadresse. + %1$s muutis selle jututoa põhiaadressi ja täiendavaid aadresse. + + Sa eemaldasid selle jututoa täiendava aadressi %1$s. + Sa eemaldasid selle jututoa täiendavad aadressid %1$s. + + + %1$s eemaldas selle jututoa täiendava aadressi %2$s. + %1$s eemaldas selle jututoa täiendavad aadressid %2$s. + + + Sa lisasid sellele jututoale täiendava aadressi %1$s. + Sa lisasid sellele jututoale täiendavad aadressid %1$s. + + + %1$s lisas sellele jututoale täiendava aadressi %2$s. + %1$s lisas sellele jututoale täiendavad aadressid %2$s. + + Sa muutsid selle jututoa aadresse. \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-fa/strings.xml b/matrix-sdk-android/src/main/res/values-fa/strings.xml index 8f8059067e..50446b9708 100644 --- a/matrix-sdk-android/src/main/res/values-fa/strings.xml +++ b/matrix-sdk-android/src/main/res/values-fa/strings.xml @@ -218,4 +218,5 @@ %1$s، %2$s، %3$s و %4$d نفر دیگر %1$s، %2$s و %3$s + %1$s، %2$s، %3$s و %4$s \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-it/strings.xml b/matrix-sdk-android/src/main/res/values-it/strings.xml index c1a5cf85cb..ec19cd5c17 100644 --- a/matrix-sdk-android/src/main/res/values-it/strings.xml +++ b/matrix-sdk-android/src/main/res/values-it/strings.xml @@ -102,7 +102,7 @@ %1$s ha rimosso %2$s come indirizzo per questa stanza. - %1$s ha rimosso %3$s come indirizzi per questa stanza. + %1$s ha rimosso %2$s come indirizzi per questa stanza. %1$s ha aggiunto %2$s e rimosso %3$s come indirizzi per questa stanza. %1$s ha impostato l\'indirizzo principale per questa stanza a %2$s. @@ -237,4 +237,26 @@ • I server che corrispondono a %s sono banditi. Hai impostato le ACL del server per questa stanza. %s ha impostato le ACL del server per questa stanza. + Hai cambiato gli indirizzi per questa stanza. + %1$s ha cambiato gli indirizzi per questa stanza. + Hai cambiato gli indirizzi principali ed alternativi per questa stanza. + %1$s ha cambiato gli indirizzi principali ed alternativi per questa stanza. + Hai cambiato gli indirizzi alternativi per questa stanza. + %1$s ha cambiato gli indirizzi alternativi per questa stanza. + + Hai rimosso l\'indirizzo alternativo %1$s per questa stanza. + Hai rimosso gli indirizzi alternativi %1$s per questa stanza. + + + %1$s ha rimosso l\'indirizzo alternativo %2$s per questa stanza. + %1$s ha rimosso gli indirizzi alternativi %2$s per questa stanza. + + + Hai aggiunto l\'indirizzo alternativo %1$s per questa stanza. + Hai aggiunto gli indirizzi alternativi %1$s per questa stanza. + + + %1$s ha aggiunto l\'indirizzo alternativo %2$s per questa stanza. + %1$s ha aggiunto gli indirizzi alternativi %2$s per questa stanza. + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-lv/strings.xml b/matrix-sdk-android/src/main/res/values-lv/strings.xml index b14cbb4b00..ec107b47d6 100644 --- a/matrix-sdk-android/src/main/res/values-lv/strings.xml +++ b/matrix-sdk-android/src/main/res/values-lv/strings.xml @@ -1,8 +1,7 @@ - + %1$s: %2$s %1$s nosūtīja attēlu. - %s\'s uzaicinājums %1$s uzaicināja %2$s %1$s uzaicināja tevi @@ -30,46 +29,56 @@ ikviens. nezināms (%s). %1$s ieslēdza ierīce-ierīce šifrēšanu (%2$s) - %1$s vēlas VoIP konferenci VoIP konference sākusies VoIP konference ir beigusies - (arī profila attēls mainījās) %1$s dzēsa istabas nosaukumu %1$s dzēsa istabas tēmas nosaukumu %1$s atjaunoja profila informāciju %2$s %1$s nosūtīja uzaicinājumu %2$s pievienoties istabai %1$s apstiprināja uzaicinājumu priekš %2$s - ** Nav iespējams atkodēt: %s ** Sūtītāja ierīce mums nenosūtīja atslēgas priekš šīs ziņas. - Nevarēja rediģēt Nav iespējams nosūtīt ziņu - Neizdevās augšuplādēt attēlu - Tīkla kļūda Matrix kļūda - Šobrīd nav iespējams atkārtoti pievienoties tukšai istabai. - Šifrēta ziņa - Epasta adrese Telefona numurs - Uzaicinājums no %s Uzaicinājums uz istabu %1$s un %2$s Tukša istaba - %1$s un 1 cits %1$s un %2$d citi %1$s un %2$d citu - - - + Tu nomainīji savu attēlojamo vārdu no %1$s uz %2$s + Tu nomainījis savu attēlojamo vārdu uz %1$s + Tu nomainīji savu avataru + Tu atsauci %1$s uzaicinājumu + Tu nobanoji %1$s + Tu atbanoji %1$s + Tu izspēri %1$s + Tu noraidīji uzaicinājumu + Tu pameti telpu + %1$s atstāja telpu + Tu atstāji telpu + Tu pievienojies + %1$s pievienojās telpai + Tu pievienojies telpai + Tu uzaicināji %1$s + Tu izveidoji apspriedi (diskusiju) + %1$s izveidoja apspriedi (diskusiju) + Tu izveidoji istabu + %1$s izveidoja telpu + Tavs uzaicinājums + Tu nosūtīji uzlīmi/lipekli. + %1$s nosūtīja uzlīmi/lipekli. + Tu nosūtīji attēlu. + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-nb/strings.xml b/matrix-sdk-android/src/main/res/values-nb/strings.xml new file mode 100644 index 0000000000..07cf4226e0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-nb/strings.xml @@ -0,0 +1,11 @@ + + + Du opprettet diskusjonen + Du opprettet rommet + Invitasjonen din + Du sendte et klistremerke. + %1$s sendte et klistremerke. + Du sendte et bilde. + %1$s sendte et bilde. + %1$s: %2$s + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-nn/strings.xml b/matrix-sdk-android/src/main/res/values-nn/strings.xml index d986e697ad..441d568fc3 100644 --- a/matrix-sdk-android/src/main/res/values-nn/strings.xml +++ b/matrix-sdk-android/src/main/res/values-nn/strings.xml @@ -1,12 +1,9 @@ - + Kryptert melding - - %1$s: %2$s %1$s sende eit bilæte. %1$s sende eit klistremerke. - %s si innbjoding %1$s inviterte %2$s %1$s inviterte deg @@ -34,53 +31,38 @@ kven som heldst. uvisst (%s). %1$s skrudde ende-til-ende-kryptering på (%2$s) - %1$s bad um ei VoIP-gruppasamtala VoIP-gruppasamtala er starta VoIP-gruppasamtala er ferdug - (avataren vart au byta) %1$s tok burt romnamnet %1$s tok burt romemnet %1$s gjorde um på skildringi si %2$s %1$s inviterte %2$s til rommet %1$s sa ja til innbjodingi til %2$s - ** Fekk ikkje til å dekryptera: %s ** Avsendareiningi hev ikkje sendt oss nyklane fyr denna meldingi. - Kunde ikkje gjera um - Fekk ikkje å senda meldingi - + Fekk ikkje til å senda meldingi Fekk ikkje til å lasta biletet upp - Noko gjekk gale med netverket Noko gjekk gale med Matrix - Det lèt seg fyrebils ikkje gjera å fara inn att i eit tomt rom. - Epostadresse Telefonnummer - Innbjoding frå %s Rominnbjoding %1$s og %2$s - %1$s og 1 til %1$s og %2$d til - Tomt rom - Ei melding vart stroki %1$s strauk meldingi Meldingi vart stroki [av di: %1$s] %1$s strauk meldingi [av di: %2$s] - %s oppgraderte rommet. - Nullstill sendingskø - %1$s forlot rommet. Grunn: %2$s - + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml index e6c93cb55c..5e3282a305 100644 --- a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml +++ b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml @@ -178,7 +178,7 @@ %1$s removeu %2$s como um endereço desta sala. - %1$s removeu %3$s como endereços desta sala. + %1$s removeu %2$s como endereços desta sala. Você removeu %1$s como um endereço desta sala. @@ -244,4 +244,26 @@ • Servidores correspondentes à %s estão banidos. Você definiu a lista de controle de acesso (ACL) do servidor para esta sala. %s definiu a lista de controle de acesso (ACL) do servidor para esta sala. + Você alterou os endereços alternativos desta sala. + %1$s alterou os endereços alternativos desta sala. + + Você removeu o endereço alternativo %1$s para esta sala. + Você removeu os endereços alternativos %1$s para esta sala. + + + %1$s removeu o endereço alternativo %2$s para esta sala. + %1$s removeu os endereços alternativos %2$s para esta sala. + + + Você adicionou o endereço alternativo %1$s para esta sala. + Você adicionou os endereços alternativos %1$s para esta sala. + + + %1$s adicionou o endereço alternativo %2$s para esta sala. + %1$s adicionou os endereços alternativos %2$s para esta sala. + + Você alterou os endereços desta sala. + %1$s alterou os endereços desta sala. + Você alterou os endereços principal e alternativos desta sala. + %1$s alterou os endereços principal e alternativos desta sala. \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-ru/strings.xml b/matrix-sdk-android/src/main/res/values-ru/strings.xml index 5ef5a4f447..f2e0bd668f 100644 --- a/matrix-sdk-android/src/main/res/values-ru/strings.xml +++ b/matrix-sdk-android/src/main/res/values-ru/strings.xml @@ -252,4 +252,34 @@ %s изменил права доступа сервера (ACL) для этой комнаты. Вы настроили права доступа сервера (ACL) для этой комнаты. %s устанавливает права доступа сервера (ACL) для этой комнаты. + Вы изменили адреса этой комнаты. + %1$s изменил(а) адреса этой комнаты. + Вы изменили основной и альтернативный адреса этой комнаты. + %1$s изменил(а) основной и альтернативный адреса этой комнаты. + Вы изменили альтернативные адреса для этой комнаты. + %1$s изменил(а) альтернативные адреса для этой комнаты. + + Вы удалили альтернативный адрес %1$s для этой комнаты. + Вы удалили альтернативные адреса %1$s для этой комнаты. + Вы удалили альтернативные адреса %1$s для этой комнаты. + Вы удалили альтернативные адреса %1$s для этой комнаты. + + + %1$s удалил(а) альтернативный адрес %2$s для этой комнаты. + %1$s удалил(а) альтернативные адреса %2$s для этой комнаты. + %1$s удалил(а) альтернативные адреса %2$s для этой комнаты. + %1$s удалил(а) альтернативные адреса %2$s для этой комнаты. + + + Вы добавили альтернативный адрес %1$s для этой комнаты. + Вы добавили альтернативные адреса %1$s для этой комнаты. + Вы добавили альтернативные адреса %1$s для этой комнаты. + Вы добавили альтернативные адреса %1$s для этой комнаты. + + + %1$s добавил(а) альтернативный адрес %2$s для этой комнаты. + %1$s добавил(а) альтернативные адреса %2$s для этой комнаты. + %1$s добавил(а) альтернативные адреса %2$s для этой комнаты. + %1$s добавил(а) альтернативные адреса %2$s для этой комнаты. + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-sk/strings.xml b/matrix-sdk-android/src/main/res/values-sk/strings.xml index 15924d02e1..a40654f7bf 100644 --- a/matrix-sdk-android/src/main/res/values-sk/strings.xml +++ b/matrix-sdk-android/src/main/res/values-sk/strings.xml @@ -197,4 +197,16 @@ %1$s povolil/a E2E šifrovanie (Nerozpoznaný algorytmus %2$s). Povolili ste E2E šifrovanie (Nerozpoznaný algorytmus %1$s). %s požaduje overenie vašich šifrovacích kľúčov, ale váš klient nepodporuje overenie kľúčov v konverzácii. Budete musieť použiť zastaralú metódu overenia. + nastavili ste na servery pravidlá ACL tejto miestnosti. + %s nastavil(a) na servery pravidlá ACL tejto miestnosti. + Aktualizovali ste sem. + %s aktualizoval(a) sem. + %1$s sprístupnil(a) budúce správy %2$s + Sprístupnili ste budúce správy %1$s + Opustili ste miestnosť + %1$s opustil(a) miestnosť + Vstúpili ste + %1$s vstúpil(a) + Vytvorili ste konverzáciu + %1$s vytvoril(a) konverzáciu \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-sq/strings.xml b/matrix-sdk-android/src/main/res/values-sq/strings.xml index 58ba8877bb..0d4b2888ba 100644 --- a/matrix-sdk-android/src/main/res/values-sq/strings.xml +++ b/matrix-sdk-android/src/main/res/values-sq/strings.xml @@ -101,7 +101,7 @@ %1$s hoqi %2$s si adresë për këtë dhomë. - %1$s hoqi %3$s si adresa për këtë dhomë. + %1$s hoqi %2$s si adresa për këtë dhomë. %1$s shtoi %2$s dhe hoqi %3$s si adresa për këtë dhomë. %1$s caktoi %2$s si adresë kryesore për këtë dhomë. @@ -232,4 +232,26 @@ • Shërbyesit që kanë përputhje me %s tani janë të ndaluar. • Shërbyesit që kanë përputhje me %s janë të ndaluar. • Shërbyesit që kanë përputhje me %s janë të ndaluar. + Ndryshuat adresat për këtë dhomë. + %1$s ndryshoi adresat për këtë dhomë. + Ndryshuat adresat kryesore dhe alternative për këtë dhomë. + %1$s ndryshoi adresat kryesore dhe alternative për këtë dhomë. + Ndryshuat adresat alternative për këtë dhomë. + %1$s ndryshoi adresat alternative për këtë dhomë. + + Hoqët adresën alternative %1$s për këtë dhomë. + Hoqët adresat alternative %1$s për këtë dhomë. + + + %1$s hoqët adresën alternative %2$s për këtë dhomë. + %1$s hoqët adresat alternative %2$s për këtë dhomë. + + + Shtuat adresën alternative %1$s për këtë dhomë. + Shtuat adresat alternative %1$s për këtë dhomë. + + + %1$s shtoi adresën alternative %2$s për këtë dhomë. + %1$s shtoi adresat alternative %2$s për këtë dhomë. + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-sv/strings.xml b/matrix-sdk-android/src/main/res/values-sv/strings.xml index d42c6ba2ca..91d874591f 100644 --- a/matrix-sdk-android/src/main/res/values-sv/strings.xml +++ b/matrix-sdk-android/src/main/res/values-sv/strings.xml @@ -213,4 +213,49 @@ %1$s gick med Du skapade diskussionen %1$s skapade diskussionen + Du ändrade adresserna för det här rummet. + %1$s ändrade adresserna för det här rummet. + Du ändrade huvudadressen och de alternativa adresserna för det här rummet. + %1$s ändrade huvudadressen och de alternativa adresserna för det här rummet. + Du ändrade de alternativa adresserna för det här rummet. + %1$s ändrade de alternativa adresserna för det här rummet. + + Du tog bort den alternativa adressen %1$s för det här rummet. + Du tog bort de alternativa adresserna %1$s för det här rummet. + + + %1$s tog bort den alternativa adressen %2$s för det här rummet. + %1$s tog bort de alternativa adresserna %2$s för det här rummet. + + + Du lade till den alternativa adressen %1$s för det här rummet. + Du lade till de alternativa adresserna %1$s för det här rummet. + + + %1$s lade till den alternativa adressen %2$s för det här rummet. + %1$s lade till de alternativa adresserna %2$s för det här rummet. + + Tomt rum (var %s) + + %1$s, %2$s, %3$s och %4$d till + %1$s, %2$s, %3$s och %4$d till + + %1$s, %2$s, %3$s och %4$s + %1$s, %2$s och %3$s + 🎉 Alla servrar har bannats från att delta! Det här rummet kan inte användas längre. + Ingen ändring. + • Servrar som matchar IP-adresser är nu bannade. + • Servrar som matchar IP-adresser är nu tillåtna. + • Servrar som matchar %s togs bort från tillåtelselistan. + • Servrar som matchar %s är nu tillåtna. + • Servrar som matchar %s togs bort från bannlistan. + • Servrar som matchar %s är nu bannade. + Du ändrade server-ACLer för det här rummet. + %s ändrade server-ACLer för det här rummet. + • Servrar som matchar IP-adresser är tillåtna. + • Servrar som matchar IP-adresser är bannade. + • Servrar som matchar %s är tillåtna. + • Servrar som matchar %s är bannade. + Du satte server-ACLer för det här rummet. + %s satte server-ACLer för det här rummet. \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-szl/strings.xml b/matrix-sdk-android/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..a6b3daec93 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-szl/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-uk/strings.xml b/matrix-sdk-android/src/main/res/values-uk/strings.xml index 2477487379..0f45a7182c 100644 --- a/matrix-sdk-android/src/main/res/values-uk/strings.xml +++ b/matrix-sdk-android/src/main/res/values-uk/strings.xml @@ -13,7 +13,7 @@ %1$s надіслав(ла) наліпку. %1$s запросив(ла) Вас %1$s приєднується - %1$s покинув(ла) + %1$s покидає кімнату %1$s відхилив(ла) запрошення %1$s копнув(ла) %2$s %1$s розблокував(ла) %2$s @@ -65,4 +65,23 @@ Повідомлення видалено %1$s видалили повідомлення Повідомлення видалено [причина: %1$s] + Початкове налаштування: +\nІмпортування даних облікового запису + Ви покинули. Причина: %1$s + %1$s покидає. Причина: %2$s + Ви покинули кімнату. Причина: %1$s + %1$s покидає кімнату. Причина: %2$s + %1$s покидає кімнату + Ви покинули кімнату + Ви покинули кімнату + Ви змінили адреси цієї кімнати. + Ви змінили основну та альтернативну адреси цієї кімнати. + Ви змінили альтернативні адреси для цієї кімнати. + Ви змінили рівень доступу на %1$s. + Ви змінили серверні списки контролю доступу для цієї кімнати. + Ви змінили назву кімнати на: %1$s + Ви змінили світлину кімнати + Ви змінили тему на: %1$s + Ви змінили показуване ім\'я з %1$s на %2$s + Ви змінили світлину профілю \ No newline at end of file diff --git a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml index 08050b400d..5038e8aab2 100644 --- a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml +++ b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml @@ -98,7 +98,7 @@ %1$s 新增了 %2$s 為此聊天室的地址。 - %1$s 移除了此聊天室的 %3$s 地址。 + %1$s 移除了此聊天室的 %2$s 地址。 %1$s 為此聊天室新增 %2$s 並移除 %3$s 地址。 %1$s 為此聊天室設定了 %2$s 為主地址。 @@ -230,4 +230,22 @@ • 已禁止伺服器符合 %s。 您為此聊天是設定了伺服器 ACL。 %s 為此聊天是設定了伺服器 ACL。 + 您變更了此聊天室的地址。 + %1$s 變更了此聊天室的地址。 + 您為此聊天室變更了主要及備用地址。 + %1$s 為此聊天室變更了主要及備用地址。 + 您為此聊天室變更了備用地址。 + %1$s 變更了此聊天室的備用地址。 + + 您為此聊天室移除了備用地址 %1$s。 + + + %1$s 已為此聊天室移除備用地址 %2$s。 + + + 您為此聊天室新增了備用地址 %1$s。 + + + %1$s 已為此聊天室新增了備用地址 %2$s。 + \ No newline at end of file diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt index 667e0b2471..74b6c03d93 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt @@ -38,19 +38,16 @@ class CoroutineSequencersTest: MatrixTest { val jobs = listOf( GlobalScope.launch(dispatcher) { - sequencer.post { suspendingMethod("#1") }.also { - results.add(it) - } + sequencer.post { suspendingMethod("#1") } + .also { results.add(it) } }, GlobalScope.launch(dispatcher) { - sequencer.post { suspendingMethod("#2") }.also { - results.add(it) - } + sequencer.post { suspendingMethod("#2") } + .also { results.add(it) } }, GlobalScope.launch(dispatcher) { - sequencer.post { suspendingMethod("#3") }.also { - results.add(it) - } + sequencer.post { suspendingMethod("#3") } + .also { results.add(it) } } ) runBlocking { @@ -70,19 +67,16 @@ class CoroutineSequencersTest: MatrixTest { val results = ArrayList() val jobs = listOf( GlobalScope.launch(dispatcher) { - sequencer1.post { suspendingMethod("#1") }.also { - results.add(it) - } + sequencer1.post { suspendingMethod("#1") } + .also { results.add(it) } }, GlobalScope.launch(dispatcher) { - sequencer2.post { suspendingMethod("#2") }.also { - results.add(it) - } + sequencer2.post { suspendingMethod("#2") } + .also { results.add(it) } }, GlobalScope.launch(dispatcher) { - sequencer3.post { suspendingMethod("#3") }.also { - results.add(it) - } + sequencer3.post { suspendingMethod("#3") } + .also { results.add(it) } } ) runBlocking { @@ -97,20 +91,17 @@ class CoroutineSequencersTest: MatrixTest { val results = ArrayList() val jobs = listOf( GlobalScope.launch(dispatcher) { - sequencer.post { suspendingMethod("#1") }.also { - results.add(it) - } + sequencer.post { suspendingMethod("#1") } + .also { results.add(it) } }, GlobalScope.launch(dispatcher) { - val result = sequencer.post { suspendingMethod("#2") }.also { - results.add(it) - } - println("Result: $result") + sequencer.post { suspendingMethod("#2") } + .also { results.add(it) } + .also { println("Result: $it") } }, GlobalScope.launch(dispatcher) { - sequencer.post { suspendingMethod("#3") }.also { - results.add(it) - } + sequencer.post { suspendingMethod("#3") } + .also { results.add(it) } } ) // We are canceling the second job diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index b9929dfebe..2306eaed8b 100644 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -161,7 +161,7 @@ Formatter\.formatShortFileSize===1 # android\.text\.TextUtils ### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt -enum class===84 +enum class===85 ### Do not import temporary legacy classes import org.matrix.android.sdk.internal.legacy.riot===3 diff --git a/tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl b/tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl index d3c50c961c..8c25f9f9a8 100644 --- a/tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl +++ b/tools/templates/ElementFeature/root/src/app_package/ViewModel.kt.ftl @@ -4,8 +4,9 @@ import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -21,7 +22,7 @@ class ${viewModelClass} @AssistedInject constructor(@Assisted initialState: ${vi : VectorViewModel<${viewStateClass}, ${actionClass}, EmptyViewEvents>(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ${viewStateClass}): ${viewModelClass} } diff --git a/vector/build.gradle b/vector/build.gradle index f6ba5d6e27..71cbe532c3 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -13,7 +13,7 @@ kapt { // Note: 2 digits max for each value ext.versionMajor = 1 ext.versionMinor = 0 -ext.versionPatch = 14 +ext.versionPatch = 15 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' @@ -291,7 +291,7 @@ dependencies { def big_image_viewer_version = '1.6.2' def glide_version = '4.11.0' def moshi_version = '1.11.0' - def daggerVersion = '2.29.1' + def daggerVersion = '2.31' def autofill_version = "1.0.0" def work_version = '2.4.0' def arch_version = '2.1.0' @@ -412,8 +412,6 @@ dependencies { // DI implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" - compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0' - kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0' // gplay flavor only gplayImplementation('com.google.firebase:firebase-messaging:21.0.0') { diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index cc4724e8f3..58b596b05f 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -247,6 +247,7 @@ class UiAllScreensSanityTest { // Room settings clickListItem(R.id.matrixProfileRecyclerView, 3) + navigateToRoomParameters() pressBack() // Notifications @@ -285,6 +286,31 @@ class UiAllScreensSanityTest { pressBack() } + private fun navigateToRoomParameters() { + // Room addresses + clickListItem(R.id.roomSettingsRecyclerView, 4) + onView(isRoot()).perform(waitForView(withText(R.string.room_alias_published_alias_title))) + pressBack() + + // Room permissions + clickListItem(R.id.roomSettingsRecyclerView, 6) + onView(isRoot()).perform(waitForView(withText(R.string.room_permissions_title))) + clickOn(R.string.room_permissions_change_room_avatar) + clickDialogNegativeButton() + // Toggle + clickOn(R.string.show_advanced) + clickOn(R.string.hide_advanced) + pressBack() + + // Room history readability + clickListItem(R.id.roomSettingsRecyclerView, 8) + pressBack() + + // Room access + clickListItem(R.id.roomSettingsRecyclerView, 10) + pressBack() + } + private fun navigateToInvite() { assertDisplayed(R.id.inviteUsersButton) clickOn(R.id.inviteUsersButton) diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt b/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt index 674e7dfef5..b94e99208b 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt +++ b/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt @@ -26,37 +26,36 @@ import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import im.vector.app.core.di.HasVectorInjector import im.vector.app.core.services.VectorSyncService -import im.vector.app.features.settings.VectorPreferences import org.matrix.android.sdk.internal.session.sync.job.SyncService import timber.log.Timber class AlarmSyncBroadcastReceiver : BroadcastReceiver() { - lateinit var vectorPreferences: VectorPreferences - override fun onReceive(context: Context, intent: Intent) { - val appContext = context.applicationContext - if (appContext is HasVectorInjector) { - val activeSession = appContext.injector().activeSessionHolder().getSafeActiveSession() - if (activeSession == null) { - Timber.v("No active session don't launch sync service.") - return - } - vectorPreferences = appContext.injector().vectorPreferences() - } + Timber.d("## Sync: AlarmSyncBroadcastReceiver received intent") + val vectorPreferences = (context.applicationContext as? HasVectorInjector) + ?.injector() + ?.takeIf { it.activeSessionHolder().getSafeActiveSession() != null } + ?.vectorPreferences() + ?: return Unit.also { Timber.v("No active session, so don't launch sync service.") } val sessionId = intent.getStringExtra(SyncService.EXTRA_SESSION_ID) ?: return - // This method is called when the BroadcastReceiver is receiving an Intent broadcast. - Timber.d("RestartBroadcastReceiver received intent") - VectorSyncService.newPeriodicIntent(context, sessionId, vectorPreferences.backgroundSyncTimeOut(), vectorPreferences.backgroundSyncDelay()).let { - try { - ContextCompat.startForegroundService(context, it) - } catch (ex: Throwable) { - Timber.i("## Sync: Failed to start service, Alarm scheduled to restart service") - scheduleAlarm(context, sessionId, vectorPreferences.backgroundSyncDelay()) - Timber.e(ex) - } - } + VectorSyncService.newPeriodicIntent( + context = context, + sessionId = sessionId, + syncTimeoutSeconds = vectorPreferences.backgroundSyncTimeOut(), + syncDelaySeconds = vectorPreferences.backgroundSyncDelay(), + isNetworkBack = false + ) + .let { + try { + ContextCompat.startForegroundService(context, it) + } catch (ex: Throwable) { + Timber.i("## Sync: Failed to start service, Alarm scheduled to restart service") + scheduleAlarm(context, sessionId, vectorPreferences.backgroundSyncDelay()) + Timber.e(ex) + } + } } companion object { diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 4ad51fdea7..0341059674 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -82,8 +82,7 @@ + android:name=".features.home.HomeActivity" /> Copyright 2018 The diff-match-patch Authors. https://github.com/google/diff-match-patch -
  • - EventBus -
    - Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org) -
  • LazyThreeTenBp
    diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 87ab875746..407aa2fc73 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -84,6 +84,7 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment import im.vector.app.features.roomprofile.members.RoomMemberListFragment import im.vector.app.features.roomprofile.settings.RoomSettingsFragment import im.vector.app.features.roomprofile.alias.RoomAliasFragment +import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment @@ -364,6 +365,11 @@ interface FragmentModule { @FragmentKey(RoomAliasFragment::class) fun bindRoomAliasFragment(fragment: RoomAliasFragment): Fragment + @Binds + @IntoMap + @FragmentKey(RoomPermissionsFragment::class) + fun bindRoomPermissionsFragment(fragment: RoomPermissionsFragment): Fragment + @Binds @IntoMap @FragmentKey(RoomMemberProfileFragment::class) diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt index f56a6a3d70..e3ba70ea09 100644 --- a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt @@ -86,7 +86,6 @@ import im.vector.app.features.workers.signout.SignOutBottomSheetDialogFragment VectorComponent::class ], modules = [ - AssistedInjectModule::class, ViewModelModule::class, FragmentModule::class, HomeModule::class, diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt index 3dceec48ef..218a22533a 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt @@ -18,6 +18,7 @@ package im.vector.app.core.epoxy import android.animation.ObjectAnimator import android.text.TextUtils +import android.text.method.MovementMethod import android.widget.ImageView import android.widget.TextView import androidx.core.view.doOnPreDraw @@ -36,6 +37,9 @@ abstract class ExpandableTextItem : VectorEpoxyModel( @EpoxyAttribute var maxLines: Int = 3 + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var movementMethod: MovementMethod? = null + private var isExpanded = false private var expandedLines = 0 @@ -43,6 +47,7 @@ abstract class ExpandableTextItem : VectorEpoxyModel( super.bind(holder) holder.content.text = content holder.content.copyOnLongClick() + holder.content.movementMethod = movementMethod holder.content.doOnPreDraw { if (holder.content.lineCount > maxLines) { diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index cb87947612..10dade70ea 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -38,14 +38,18 @@ fun Session.startSyncing(context: Context) { val applicationContext = context.applicationContext if (!hasAlreadySynced()) { // initial sync is done as a service so it can continue below app lifecycle - VectorSyncService.newOneShotIntent(applicationContext, sessionId, 0).also { - try { - ContextCompat.startForegroundService(applicationContext, it) - } catch (ex: Throwable) { - // TODO - Timber.e(ex) - } - } + VectorSyncService.newOneShotIntent( + context = applicationContext, + sessionId = sessionId + ) + .let { + try { + ContextCompat.startForegroundService(applicationContext, it) + } catch (ex: Throwable) { + // TODO + Timber.e(ex) + } + } } else { val isAtLeastStarted = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) Timber.v("--> is at least started? $isAtLeastStarted") diff --git a/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt index 38977d33ba..5037f78445 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt @@ -16,26 +16,6 @@ package im.vector.app.core.extensions -import java.net.URLEncoder - -/** - * Append param and value to a Url, using "?" or "&". Value parameter will be encoded - * Return this for chaining purpose - */ -fun StringBuilder.appendParamToUrl(param: String, value: String): StringBuilder { - if (contains("?")) { - append("&") - } else { - append("?") - } - - append(param) - append("=") - append(URLEncoder.encode(value, "utf-8")) - - return this -} - /** * Ex: "https://matrix.org/" -> "matrix.org" */ diff --git a/vector/src/main/java/im/vector/app/core/files/LocalFilesHelper.kt b/vector/src/main/java/im/vector/app/core/files/LocalFilesHelper.kt new file mode 100644 index 0000000000..d9cf4fc484 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/files/LocalFilesHelper.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.files + +import android.content.Context +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import org.matrix.android.sdk.api.extensions.orFalse +import java.io.InputStream +import javax.inject.Inject + +class LocalFilesHelper @Inject constructor(private val context: Context) { + fun isLocalFile(fileUri: String?): Boolean { + return fileUri + ?.let { Uri.parse(it) } + ?.let { DocumentFile.fromSingleUri(context, it) } + ?.exists() + .orFalse() + } + + fun openInputStream(fileUri: String?): InputStream? { + return fileUri + ?.takeIf { isLocalFile(it) } + ?.let { Uri.parse(it) } + ?.let { context.contentResolver.openInputStream(it) } + } +} diff --git a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt index a51410165b..6ded33f823 100644 --- a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt +++ b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt @@ -24,7 +24,6 @@ import com.bumptech.glide.GlideBuilder import com.bumptech.glide.Registry import com.bumptech.glide.annotation.GlideModule import com.bumptech.glide.module.AppGlideModule -import im.vector.app.core.extensions.vectorComponent import im.vector.app.features.media.ImageContentRenderer import java.io.InputStream @@ -36,8 +35,10 @@ class MyAppGlideModule : AppGlideModule() { } override fun registerComponents(context: Context, glide: Glide, registry: Registry) { - registry.append(ImageContentRenderer.Data::class.java, + registry.append( + ImageContentRenderer.Data::class.java, InputStream::class.java, - VectorGlideModelLoaderFactory(context.vectorComponent().activeSessionHolder())) + VectorGlideModelLoaderFactory(context) + ) } } diff --git a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt index 9a7cf1eb76..81e81bb78a 100644 --- a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt +++ b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt @@ -16,6 +16,7 @@ package im.vector.app.core.glide +import android.content.Context import com.bumptech.glide.Priority import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.Options @@ -24,7 +25,8 @@ import com.bumptech.glide.load.model.ModelLoader import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.MultiModelLoaderFactory import com.bumptech.glide.signature.ObjectKey -import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.extensions.vectorComponent +import im.vector.app.core.files.LocalFilesHelper import im.vector.app.features.media.ImageContentRenderer import okhttp3.OkHttpClient import org.matrix.android.sdk.api.MatrixCallback @@ -33,11 +35,10 @@ import java.io.File import java.io.IOException import java.io.InputStream -class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessionHolder) - : ModelLoaderFactory { +class VectorGlideModelLoaderFactory(private val context: Context) : ModelLoaderFactory { override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { - return VectorGlideModelLoader(activeSessionHolder) + return VectorGlideModelLoader(context) } override fun teardown() { @@ -45,7 +46,7 @@ class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessi } } -class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolder) +class VectorGlideModelLoader(private val context: Context) : ModelLoader { override fun handles(model: ImageContentRenderer.Data): Boolean { // Always handle @@ -53,16 +54,19 @@ class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolde } override fun buildLoadData(model: ImageContentRenderer.Data, width: Int, height: Int, options: Options): ModelLoader.LoadData? { - return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(activeSessionHolder, model, width, height)) + return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(context, model, width, height)) } } -class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolder, +class VectorGlideDataFetcher(context: Context, private val data: ImageContentRenderer.Data, private val width: Int, private val height: Int) : DataFetcher { + private val localFilesHelper = LocalFilesHelper(context) + private val activeSessionHolder = context.vectorComponent().activeSessionHolder() + private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient() override fun getDataClass(): Class { @@ -97,9 +101,10 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde override fun loadData(priority: Priority, callback: DataFetcher.DataCallback) { Timber.v("Load data: $data") - if (data.isLocalFile && data.url != null) { - val initialFile = File(data.url) - callback.onDataReady(initialFile.inputStream()) + if (localFilesHelper.isLocalFile(data.url)) { + localFilesHelper.openInputStream(data.url)?.use { + callback.onDataReady(it) + } return } // val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() diff --git a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt index bf78d5b7fb..2a00e94976 100644 --- a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt +++ b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt @@ -21,7 +21,6 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.os.Build -import androidx.core.content.ContextCompat.getSystemService import androidx.core.content.getSystemService import androidx.work.Constraints import androidx.work.Data @@ -34,6 +33,7 @@ import androidx.work.WorkerParameters import im.vector.app.R import im.vector.app.core.extensions.vectorComponent import im.vector.app.features.notifications.NotificationUtils +import im.vector.app.features.settings.BackgroundSyncMode import org.matrix.android.sdk.internal.session.sync.job.SyncService import timber.log.Timber @@ -41,30 +41,26 @@ class VectorSyncService : SyncService() { companion object { - fun newOneShotIntent(context: Context, sessionId: String, timeoutSeconds: Int): Intent { + fun newOneShotIntent(context: Context, + sessionId: String): Intent { return Intent(context, VectorSyncService::class.java).also { it.putExtra(EXTRA_SESSION_ID, sessionId) - it.putExtra(EXTRA_TIMEOUT_SECONDS, timeoutSeconds) + it.putExtra(EXTRA_TIMEOUT_SECONDS, 0) it.putExtra(EXTRA_PERIODIC, false) } } - fun newPeriodicIntent(context: Context, sessionId: String, timeoutSeconds: Int, delayInSeconds: Int): Intent { + fun newPeriodicIntent(context: Context, + sessionId: String, + syncTimeoutSeconds: Int, + syncDelaySeconds: Int, + isNetworkBack: Boolean): Intent { return Intent(context, VectorSyncService::class.java).also { it.putExtra(EXTRA_SESSION_ID, sessionId) - it.putExtra(EXTRA_TIMEOUT_SECONDS, timeoutSeconds) + it.putExtra(EXTRA_TIMEOUT_SECONDS, syncTimeoutSeconds) it.putExtra(EXTRA_PERIODIC, true) - it.putExtra(EXTRA_DELAY_SECONDS, delayInSeconds) - } - } - - fun newPeriodicNetworkBackIntent(context: Context, sessionId: String, timeoutSeconds: Int, delayInSeconds: Int): Intent { - return Intent(context, VectorSyncService::class.java).also { - it.putExtra(EXTRA_SESSION_ID, sessionId) - it.putExtra(EXTRA_TIMEOUT_SECONDS, timeoutSeconds) - it.putExtra(EXTRA_PERIODIC, true) - it.putExtra(EXTRA_DELAY_SECONDS, delayInSeconds) - it.putExtra(EXTRA_NETWORK_BACK_RESTART, true) + it.putExtra(EXTRA_DELAY_SECONDS, syncDelaySeconds) + it.putExtra(EXTRA_NETWORK_BACK_RESTART, isNetworkBack) } } @@ -82,6 +78,10 @@ class VectorSyncService : SyncService() { notificationUtils = vectorComponent().notificationUtils() } + override fun getDefaultSyncDelaySeconds() = BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS + + override fun getDefaultSyncTimeoutSeconds() = BackgroundSyncMode.DEFAULT_SYNC_TIMEOUT_SECONDS + override fun onStart(isInitialSync: Boolean) { val notificationSubtitleRes = if (isInitialSync) { R.string.notification_initial_sync @@ -92,20 +92,26 @@ class VectorSyncService : SyncService() { startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification) } - override fun onRescheduleAsked(sessionId: String, isInitialSync: Boolean, timeout: Int, delay: Int) { - reschedule(sessionId, timeout, delay) + override fun onRescheduleAsked(sessionId: String, + syncTimeoutSeconds: Int, + syncDelaySeconds: Int) { + rescheduleSyncService( + sessionId = sessionId, + syncTimeoutSeconds = syncTimeoutSeconds, + syncDelaySeconds = syncDelaySeconds, + isPeriodic = true, + isNetworkBack = false + ) } - override fun onNetworkError(sessionId: String, isInitialSync: Boolean, timeout: Int, delay: Int) { - Timber.d("## Sync: A network error occured during sync") - val uploadWorkRequest: WorkRequest = + override fun onNetworkError(sessionId: String, + syncTimeoutSeconds: Int, + syncDelaySeconds: Int, + isPeriodic: Boolean) { + Timber.d("## Sync: A network error occurred during sync") + val rescheduleSyncWorkRequest: WorkRequest = OneTimeWorkRequestBuilder() - .setInputData(Data.Builder() - .putString("sessionId", sessionId) - .putInt("timeout", timeout) - .putInt("delay", delay) - .build() - ) + .setInputData(RestartWhenNetworkOn.createInputData(sessionId, syncTimeoutSeconds, syncDelaySeconds, isPeriodic)) .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() @@ -115,7 +121,7 @@ class VectorSyncService : SyncService() { Timber.d("## Sync: Schedule a work to restart service when network will be on") WorkManager .getInstance(applicationContext) - .enqueue(uploadWorkRequest) + .enqueue(rescheduleSyncWorkRequest) } override fun onDestroy() { @@ -128,13 +134,79 @@ class VectorSyncService : SyncService() { notificationManager.cancel(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE) } - private fun reschedule(sessionId: String, timeout: Int, delay: Int) { - val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - PendingIntent.getForegroundService(this, 0, newPeriodicIntent(this, sessionId, timeout, delay), 0) - } else { - PendingIntent.getService(this, 0, newPeriodicIntent(this, sessionId, timeout, delay), 0) + // I do not move or rename this class, since I'm not sure about the side effect regarding the WorkManager + class RestartWhenNetworkOn(appContext: Context, workerParams: WorkerParameters) : + Worker(appContext, workerParams) { + override fun doWork(): Result { + Timber.d("## Sync: RestartWhenNetworkOn.doWork()") + val sessionId = inputData.getString(KEY_SESSION_ID) ?: return Result.failure() + val syncTimeoutSeconds = inputData.getInt(KEY_SYNC_TIMEOUT_SECONDS, BackgroundSyncMode.DEFAULT_SYNC_TIMEOUT_SECONDS) + val syncDelaySeconds = inputData.getInt(KEY_SYNC_DELAY_SECONDS, BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS) + val isPeriodic = inputData.getBoolean(KEY_IS_PERIODIC, false) + applicationContext.rescheduleSyncService( + sessionId = sessionId, + syncTimeoutSeconds = syncTimeoutSeconds, + syncDelaySeconds = syncDelaySeconds, + isPeriodic = isPeriodic, + isNetworkBack = true + ) + // Indicate whether the work finished successfully with the Result + return Result.success() } - val firstMillis = System.currentTimeMillis() + delay * 1000L + + companion object { + fun createInputData(sessionId: String, + syncTimeoutSeconds: Int, + syncDelaySeconds: Int, + isPeriodic: Boolean + ): Data { + return Data.Builder() + .putString(KEY_SESSION_ID, sessionId) + .putInt(KEY_SYNC_TIMEOUT_SECONDS, syncTimeoutSeconds) + .putInt(KEY_SYNC_DELAY_SECONDS, syncDelaySeconds) + .putBoolean(KEY_IS_PERIODIC, isPeriodic) + .build() + } + + private const val KEY_SESSION_ID = "sessionId" + private const val KEY_SYNC_TIMEOUT_SECONDS = "timeout" + private const val KEY_SYNC_DELAY_SECONDS = "delay" + private const val KEY_IS_PERIODIC = "isPeriodic" + } + } +} + +private fun Context.rescheduleSyncService(sessionId: String, + syncTimeoutSeconds: Int, + syncDelaySeconds: Int, + isPeriodic: Boolean, + isNetworkBack: Boolean) { + Timber.d("## Sync: rescheduleSyncService") + val intent = if (isPeriodic) { + VectorSyncService.newPeriodicIntent( + context = this, + sessionId = sessionId, + syncTimeoutSeconds = syncTimeoutSeconds, + syncDelaySeconds = syncDelaySeconds, + isNetworkBack = isNetworkBack + ) + } else { + VectorSyncService.newOneShotIntent( + context = this, + sessionId = sessionId + ) + } + + if (isNetworkBack || syncDelaySeconds == 0) { + // Do not wait, do the sync now (more reactivity if network back is due to user action) + startService(intent) + } else { + val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + PendingIntent.getForegroundService(this, 0, intent, 0) + } else { + PendingIntent.getService(this, 0, intent, 0) + } + val firstMillis = System.currentTimeMillis() + syncDelaySeconds * 1000L val alarmMgr = getSystemService()!! if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmMgr.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) @@ -142,28 +214,4 @@ class VectorSyncService : SyncService() { alarmMgr.set(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) } } - - class RestartWhenNetworkOn(appContext: Context, workerParams: WorkerParameters) : - Worker(appContext, workerParams) { - override fun doWork(): Result { - val sessionId = inputData.getString("sessionId") ?: return Result.failure() - val timeout = inputData.getInt("timeout", 6) - val delay = inputData.getInt("delay", 60) - - val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - PendingIntent.getForegroundService(applicationContext, 0, newPeriodicNetworkBackIntent(applicationContext, sessionId, timeout, delay), 0) - } else { - PendingIntent.getService(applicationContext, 0, newPeriodicNetworkBackIntent(applicationContext, sessionId, timeout, delay), 0) - } - val firstMillis = System.currentTimeMillis() + delay * 1000L - val alarmMgr = getSystemService(applicationContext, AlarmManager::class.java)!! - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmMgr.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) - } else { - alarmMgr.set(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) - } - // Indicate whether the work finished successfully with the Result - return Result.success() - } - } } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt b/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt index 6f261ad717..f86825750a 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt @@ -28,7 +28,7 @@ import androidx.core.view.isInvisible import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide -import im.vector.app.databinding.ItemVerificationActionBinding +import im.vector.app.databinding.ViewBottomSheetActionButtonBinding import im.vector.app.features.themes.ThemeUtils class BottomSheetActionButton @JvmOverloads constructor( @@ -36,7 +36,7 @@ class BottomSheetActionButton @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { - val views : ItemVerificationActionBinding + val views: ViewBottomSheetActionButtonBinding var title: String? = null set(value) { @@ -97,8 +97,8 @@ class BottomSheetActionButton @JvmOverloads constructor( } init { - inflate(context, R.layout.item_verification_action, this) - views = ItemVerificationActionBinding.bind(this) + inflate(context, R.layout.view_bottom_sheet_action_button, this) + views = ViewBottomSheetActionButtonBinding.bind(this) context.withStyledAttributes(attrs, R.styleable.BottomSheetActionButton) { title = getString(R.styleable.BottomSheetActionButton_actionTitle) ?: "" diff --git a/vector/src/main/java/im/vector/app/core/ui/views/NonScrollingTextView.kt b/vector/src/main/java/im/vector/app/core/ui/views/NonScrollingTextView.kt new file mode 100644 index 0000000000..712432abfd --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/ui/views/NonScrollingTextView.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.ui.views + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView + +class NonScrollingTextView : AppCompatTextView { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + + override fun scrollTo(x: Int, y: Int) { + // NOOP + } +} diff --git a/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt b/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt index aa36dd0959..b5ce922487 100644 --- a/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt @@ -24,8 +24,6 @@ import java.util.Locale // Implementation should return true in case of success typealias ActionOnFile = (file: File) -> Boolean -internal fun String?.isLocalFile() = this != null && File(this).exists() - /* ========================================================================================== * Delete * ========================================================================================== */ diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt index c29baac4ec..cb7be9ee3b 100644 --- a/vector/src/main/java/im/vector/app/features/MainActivity.kt +++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt @@ -79,8 +79,6 @@ class MainActivity : VectorBaseActivity(), UnlockedActiv intent.putExtra(EXTRA_ARGS, args) activity.startActivity(intent) - // Ensure all the Activities are destroyed, it seems that the intent flags are not enough now. - activity.finishAffinity() } } diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt index de8003b28b..b2ad0a7688 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt @@ -18,8 +18,9 @@ package im.vector.app.features.autocomplete.member import android.content.Context import androidx.recyclerview.widget.RecyclerView -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.features.autocomplete.AutocompleteClickListener import im.vector.app.features.autocomplete.RecyclerViewPresenter import org.matrix.android.sdk.api.query.QueryStringValue @@ -44,7 +45,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, controller.listener = null } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(roomId: String): AutocompleteMemberPresenter } diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt index 5fdc70c539..9aa6ccd298 100644 --- a/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt +++ b/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt @@ -18,7 +18,7 @@ package im.vector.app.features.call import android.content.Context import android.util.AttributeSet -import android.widget.LinearLayout +import android.widget.FrameLayout import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.databinding.ViewCallControlsBinding @@ -28,7 +28,7 @@ import org.webrtc.PeerConnection class CallControlsView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { +) : FrameLayout(context, attrs, defStyleAttr) { private val views: ViewCallControlsBinding diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index bd16adf3e7..fd735de085 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.MatrixCallback @@ -242,7 +243,7 @@ class VectorCallViewModel @AssistedInject constructor( }.exhaustive } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: VectorCallViewState, args: CallArgs): VectorCallViewModel } diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt index 783b519706..97ee41154a 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import org.jitsi.meet.sdk.JitsiMeetUserInfo @@ -40,7 +41,7 @@ class JitsiCallViewModel @AssistedInject constructor( private val stringProvider: StringProvider ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: JitsiCallViewState, args: VectorJitsiActivity.Args): JitsiCallViewModel } diff --git a/vector/src/main/java/im/vector/app/features/call/telecom/CallConnection.kt b/vector/src/main/java/im/vector/app/features/call/telecom/CallConnection.kt index 6f69b4b0d0..0a9a164993 100644 --- a/vector/src/main/java/im/vector/app/features/call/telecom/CallConnection.kt +++ b/vector/src/main/java/im/vector/app/features/call/telecom/CallConnection.kt @@ -21,7 +21,6 @@ import android.os.Build import android.telecom.Connection import android.telecom.DisconnectCause import androidx.annotation.RequiresApi -import im.vector.app.features.call.VectorCallViewModel import im.vector.app.features.call.WebRtcPeerConnectionManager import timber.log.Timber import javax.inject.Inject @@ -33,7 +32,6 @@ import javax.inject.Inject ) : Connection() { @Inject lateinit var peerConnectionManager: WebRtcPeerConnectionManager - @Inject lateinit var callViewModel: VectorCallViewModel init { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt index 2c4c5d0596..d73794f8d8 100644 --- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.contacts.ContactsDataSource import im.vector.app.core.contacts.MappedContact import im.vector.app.core.extensions.exhaustive @@ -48,7 +49,7 @@ class ContactsBookViewModel @AssistedInject constructor(@Assisted private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ContactsBookViewState): ContactsBookViewModel } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt index d074c93587..30bbedf7ec 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.raw.wellknown.getElementWellknown @@ -41,7 +42,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: CreateDirectRoomViewState): CreateDirectRoomViewModel } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt index 3666dbce8c..cb8a6ce4e9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.MatrixCallback @@ -39,7 +40,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS ) : VectorViewModel(initialState), KeysBackupStateListener { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: KeysBackupSettingViewState): KeysBackupSettingsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt index c7533cd3df..e95f250dd3 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -26,8 +26,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -71,7 +72,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: SharedSecureStorageViewState, args: SharedSecureStorageActivity.Args): SharedSecureStorageViewModel } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt index 2e5097fdb7..3a6f57198e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext import com.nulabinc.zxcvbn.Zxcvbn -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.extensions.exhaustive @@ -60,7 +61,7 @@ class BootstrapSharedViewModel @AssistedInject constructor( private var isBackupCreatedFromPassphrase: Boolean = false private val zxcvbn = Zxcvbn() - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: BootstrapViewState, args: BootstrapBottomSheet.Args): BootstrapSharedViewModel } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt index 23ed9b6483..04ac79d4a4 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -159,7 +160,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( super.onCleared() } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: VerificationBottomSheetViewState, args: VerificationBottomSheet.VerificationArgs): VerificationBottomSheetViewModel diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt index e309869479..7b9acd2f57 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt @@ -19,8 +19,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents @@ -79,7 +80,7 @@ class VerificationChooseMethodViewModel @AssistedInject constructor( } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel } @@ -89,8 +90,8 @@ class VerificationChooseMethodViewModel @AssistedInject constructor( } override fun onCleared() { - super.onCleared() session.cryptoService().verificationService().removeListener(this) + super.onCleared() } companion object : MvRxViewModelFactory { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt index d511123f5e..44f0e752c8 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents @@ -149,7 +150,7 @@ class VerificationEmojiCodeViewModel @AssistedInject constructor( } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt index 0f294e080a..bf2defafa1 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch @@ -42,7 +43,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor( private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: DiscoverySettingsState): DiscoverySettingsViewModel } @@ -93,8 +94,8 @@ class DiscoverySettingsViewModel @AssistedInject constructor( } override fun onCleared() { - super.onCleared() stopListenToIdentityManager() + super.onCleared() } override fun handle(action: DiscoverySettingsAction) { diff --git a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt index 0f07a0353f..9455b1bff4 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt @@ -19,8 +19,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.extensions.exhaustive @@ -41,7 +42,7 @@ class SetIdentityServerViewModel @AssistedInject constructor( stringProvider: StringProvider) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: SetIdentityServerState): SetIdentityServerViewModel } diff --git a/vector/src/main/java/im/vector/app/features/grouplist/GroupListViewModel.kt b/vector/src/main/java/im/vector/app/features/grouplist/GroupListViewModel.kt index a17aa4dbf2..3b096adbfb 100644 --- a/vector/src/main/java/im/vector/app/features/grouplist/GroupListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/grouplist/GroupListViewModel.kt @@ -22,8 +22,9 @@ import arrow.core.Option import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider @@ -45,7 +46,7 @@ class GroupListViewModel @AssistedInject constructor(@Assisted initialState: Gro private val stringProvider: StringProvider ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: GroupListViewState): GroupListViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 9d7beb13a3..108e0512a7 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -39,7 +39,6 @@ import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.ToolbarConfigurable import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.pushers.PushersManager -import im.vector.app.core.utils.toast import im.vector.app.databinding.ActivityHomeBinding import im.vector.app.features.disclaimer.showDisclaimerDialog import im.vector.app.features.matrixto.MatrixToBottomSheet @@ -166,8 +165,8 @@ class HomeActivity : private fun handleIntent(intent: Intent?) { intent?.dataString?.let { deepLink -> val resolvedLink = when { - deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> deepLink - deepLink.startsWith(PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> { + deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> deepLink + deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> { // This is a bit ugly, but for now just convert to matrix.to link for compatibility when { deepLink.startsWith(USER_LINK_PREFIX) -> deepLink.substring(USER_LINK_PREFIX.length) @@ -177,7 +176,7 @@ class HomeActivity : activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(it) } } - else -> null + else -> return@let } permalinkHandler.launch( @@ -190,7 +189,11 @@ class HomeActivity : .observeOn(AndroidSchedulers.mainThread()) .subscribe { isHandled -> if (!isHandled) { - toast(R.string.permalink_malformed) + AlertDialog.Builder(this) + .setTitle(R.string.dialog_title_error) + .setMessage(R.string.permalink_malformed) + .setPositiveButton(R.string.ok, null) + .show() } } .disposeOnDestroy() @@ -410,7 +413,8 @@ class HomeActivity : } } - private const val ROOM_LINK_PREFIX = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/" - private const val USER_LINK_PREFIX = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/" + private const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://" + private const val ROOM_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/" + private const val USER_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/" } } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index 90d128320b..45fce13ab9 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -20,8 +20,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -52,7 +53,7 @@ class HomeActivityViewModel @AssistedInject constructor( private val vectorPreferences: VectorPreferences ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: HomeActivityViewState, args: HomeActivityArgs): HomeActivityViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 88c310fde8..c261081055 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -19,8 +19,9 @@ package im.vector.app.features.home import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -44,7 +45,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho private val stringProvider: StringProvider) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: HomeDetailViewState): HomeDetailViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt index 3bdcfc4018..f4f16502ab 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModelAction @@ -65,7 +66,7 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(@Assisted data class IgnoreDevice(val deviceIds: List) : Action() } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt index 8a32157097..d3825de4ef 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt @@ -19,8 +19,9 @@ package im.vector.app.features.home.room.breadcrumbs import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -35,7 +36,7 @@ class BreadcrumbsViewModel @AssistedInject constructor(@Assisted initialState: B private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: BreadcrumbsViewState): BreadcrumbsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index d560a675fe..ec2ff82e67 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -24,8 +24,9 @@ import android.widget.EditText import com.otaliastudios.autocomplete.Autocomplete import com.otaliastudios.autocomplete.AutocompleteCallback import com.otaliastudios.autocomplete.CharPolicy -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideRequests @@ -59,7 +60,7 @@ class AutoCompleter @AssistedInject constructor( private lateinit var autocompleteMemberPresenter: AutocompleteMemberPresenter - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(roomId: String): AutoCompleter } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 8d0ed34c1e..e134230c61 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -1164,6 +1164,8 @@ class RoomDetailFragment @Inject constructor( } else false } + views.composerLayout.views.composerEmojiButton.isVisible = vectorPreferences.showEmojiKeyboard() + views.composerLayout.callback = object : TextComposerView.Callback { override fun onAddAttachment() { if (!::attachmentTypeSelector.isInitialized) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt index e4e7177e4f..ecfd1f85d3 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt @@ -25,13 +25,13 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay import com.jakewharton.rxrelay2.PublishRelay -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider -import im.vector.app.core.utils.subscribeLogError import im.vector.app.features.call.WebRtcPeerConnectionManager import im.vector.app.features.command.CommandParser import im.vector.app.features.command.ParsedCommand @@ -135,7 +135,7 @@ class RoomDetailViewModel @AssistedInject constructor( private var trackUnreadMessages = AtomicBoolean(false) private var mostRecentDisplayedEvent: TimelineEvent? = null - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomDetailViewState): RoomDetailViewModel } @@ -168,7 +168,6 @@ class RoomDetailViewModel @AssistedInject constructor( observePowerLevel() room.getRoomSummaryLive() room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT, NoOpMatrixCallback()) - room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear() // Inform the SDK that the room is displayed session.onRoomDisplayed(initialState.roomId) chatEffectManager.delegate = this @@ -889,13 +888,15 @@ class RoomDetailViewModel @AssistedInject constructor( } private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) { - val currentPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) + val newPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) ?.content - ?.toModel() ?: return + ?.toModel() + ?.setUserPowerLevel(setUserPowerLevel.userId, setUserPowerLevel.powerLevel) + ?.toContent() + ?: return launchSlashCommandFlowSuspendable { - currentPowerLevelsContent.setUserPowerLevel(setUserPowerLevel.userId, setUserPowerLevel.powerLevel) - room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, currentPowerLevelsContent.toContent()) + room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, newPowerLevelsContent) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt index ab440f6b5f..cb93cf95d2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt @@ -23,8 +23,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch @@ -46,7 +47,7 @@ class SearchViewModel @AssistedInject constructor( private var nextBatch: String? = null - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: SearchViewState): SearchViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 716fdca2ad..5008f0e0aa 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -18,8 +18,9 @@ package im.vector.app.features.home.room.detail.timeline.action import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import dagger.Lazy import im.vector.app.R import im.vector.app.core.extensions.canReact @@ -75,7 +76,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted pillsPostProcessorFactory.create(initialState.roomId) } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: MessageActionState): MessageActionsViewModel } @@ -305,7 +306,8 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted ) { add(EventSharedAction.UseKeyBackup) } - if (session.cryptoService().getCryptoDeviceInfo(session.myUserId).size > 1) { + if (session.cryptoService().getCryptoDeviceInfo(session.myUserId).size > 1 + || timelineEvent.senderInfo.userId != session.myUserId) { add(EventSharedAction.ReRequestKey(timelineEvent.eventId)) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt index e4d124dd94..fff1c8a0ff 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents @@ -61,7 +62,7 @@ class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted private val room = session.getRoom(roomId) ?: throw IllegalStateException("Shouldn't use this ViewModel without a room") - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ViewEditHistoryViewState): ViewEditHistoryViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index a1e041b98f..4f52fcb54c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -26,12 +26,12 @@ import android.view.View import dagger.Lazy import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.DebouncedClickListener import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.containsOnlyEmojis -import im.vector.app.core.utils.isLocalFile 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.ContentDownloadStateTrackerBinder @@ -94,6 +94,7 @@ import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import javax.inject.Inject class MessageItemFactory @Inject constructor( + private val localFilesHelper: LocalFilesHelper, private val colorProvider: ColorProvider, private val dimensionConverter: DimensionConverter, private val timelineMediaSizeProvider: TimelineMediaSizeProvider, @@ -205,7 +206,7 @@ class MessageItemFactory @Inject constructor( } ?: "" return MessageFileItem_() .attributes(attributes) - .izLocalFile(fileUrl.isLocalFile()) + .izLocalFile(localFilesHelper.isLocalFile(fileUrl)) .izDownloaded(session.fileService().isFileInCache( fileUrl, messageContent.getFileName(), @@ -270,7 +271,7 @@ class MessageItemFactory @Inject constructor( return MessageFileItem_() .attributes(attributes) .leftGuideline(avatarSizeProvider.leftGuideline) - .izLocalFile(messageContent.getFileUrl().isLocalFile()) + .izLocalFile(localFilesHelper.isLocalFile(messageContent.getFileUrl())) .izDownloaded(session.fileService().isFileInCache(messageContent)) .mxcUrl(mxcUrl) .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) @@ -305,7 +306,8 @@ class MessageItemFactory @Inject constructor( height = messageContent.info?.height, maxHeight = maxHeight, width = messageContent.info?.width, - maxWidth = maxWidth + maxWidth = maxWidth, + allowNonMxcUrls = informationData.sendState.isSending() ) return MessageImageVideoItem_() .attributes(attributes) @@ -343,7 +345,8 @@ class MessageItemFactory @Inject constructor( height = messageContent.videoInfo?.height, maxHeight = maxHeight, width = messageContent.videoInfo?.width, - maxWidth = maxWidth + maxWidth = maxWidth, + allowNonMxcUrls = informationData.sendState.isSending() ) val videoData = VideoContentRenderer.Data( diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineSettingsFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineSettingsFactory.kt index 1983b05ed3..01c7ad3986 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineSettingsFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineSettingsFactory.kt @@ -57,7 +57,7 @@ class TimelineSettingsFactory @Inject constructor( return map { EventTypeFilter( eventType = it, - stateKey = if (it == EventType.STATE_ROOM_MEMBER && userPreferencesProvider.shouldShowRoomMemberStateEvents()) session.myUserId else null + stateKey = if (it == EventType.STATE_ROOM_MEMBER && !userPreferencesProvider.shouldShowRoomMemberStateEvents()) session.myUserId else null ) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt index 98db0bc9b9..b121b14b4a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt @@ -25,6 +25,7 @@ import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R +import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.app.features.media.ImageContentRenderer @@ -55,7 +56,11 @@ abstract class MessageImageVideoItem : AbsMessageItem { - AlertDialog.Builder(requireContext()) - .setTitle(R.string.room_participants_leave_prompt_title) - .setMessage(R.string.room_participants_leave_prompt_msg) - .setPositiveButton(R.string.leave) { _, _ -> - roomListViewModel.handle(RoomListAction.LeaveRoom(quickAction.roomId)) - } - .setNegativeButton(R.string.cancel, null) - .show() - Unit + promptLeaveRoom(quickAction.roomId) } }.exhaustive } + private fun promptLeaveRoom(roomId: String) { + val isPublicRoom = roomListViewModel.isPublicRoom(roomId) + val message = buildString { + append(getString(R.string.room_participants_leave_prompt_msg)) + if (!isPublicRoom) { + append("\n\n") + append(getString(R.string.room_participants_leave_private_warning)) + } + } + AlertDialog.Builder(requireContext()) + .setTitle(R.string.room_participants_leave_prompt_title) + .setMessage(message) + .setPositiveButton(R.string.leave) { _, _ -> + roomListViewModel.handle(RoomListAction.LeaveRoom(roomId)) + } + .setNegativeButton(R.string.cancel, null) + .show() + .apply { + if (!isPublicRoom) { + withColoredButton(DialogInterface.BUTTON_POSITIVE) + } + } + } + override fun invalidate() = withState(roomListViewModel) { state -> when (state.asyncFilteredRooms) { is Incomplete -> renderLoading() diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index 84652506cd..6e5081a31c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.tag.RoomTag +import org.matrix.android.sdk.api.session.room.state.isPublic import org.matrix.android.sdk.rx.rx import timber.log.Timber import java.lang.Exception @@ -78,6 +79,10 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, }.exhaustive } + fun isPublicRoom(roomId: String): Boolean { + return session.getRoom(roomId)?.isPublic().orFalse() + } + // PRIVATE METHODS ***************************************************************************** private fun handleSelectRoom(action: RoomListAction.SelectRoom) = withState { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt index a062b2b034..c51c571815 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsViewModel.kt @@ -18,8 +18,9 @@ package im.vector.app.features.home.room.list.actions import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -31,7 +32,7 @@ class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initia private val session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomListQuickActionsState): RoomListQuickActionsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt b/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt index fe7a8006e0..05fd825558 100644 --- a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt @@ -20,8 +20,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents @@ -42,7 +43,7 @@ class HomeServerCapabilitiesViewModel @AssistedInject constructor( private val rawService: RawService ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: HomeServerCapabilitiesViewState): HomeServerCapabilitiesViewModel } diff --git a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt index c13f5fdfb3..716baff757 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt @@ -19,8 +19,9 @@ package im.vector.app.features.html import android.content.Context import android.text.Spannable import android.text.Spanned -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer @@ -37,7 +38,7 @@ class PillsPostProcessor @AssistedInject constructor(@Assisted private val roomI private val sessionHolder: ActiveSessionHolder) : EventHtmlRenderer.PostProcessor { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(roomId: String?): PillsPostProcessor } diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt index 21a998d8e2..a694ee36ba 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt @@ -19,8 +19,9 @@ package im.vector.app.features.invite import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider @@ -37,7 +38,7 @@ class InviteUsersToRoomViewModel @AssistedInject constructor(@Assisted private val room = session.getRoom(initialState.roomId)!! - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: InviteUsersToRoomViewState): InviteUsersToRoomViewModel } diff --git a/vector/src/main/java/im/vector/app/features/login/AbstractSSOLoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/AbstractSSOLoginFragment.kt index c20f4ddd23..3fc5037ae7 100644 --- a/vector/src/main/java/im/vector/app/features/login/AbstractSSOLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/AbstractSSOLoginFragment.kt @@ -87,7 +87,12 @@ abstract class AbstractSSOLoginFragment : AbstractLoginFragment withState(loginViewModel) { state -> if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) { // in this case we can prefetch (not other cases for privacy concerns) - prefetchUrl(state.getSsoUrl(null)) + loginViewModel.getSsoUrl( + redirectUrl = LoginActivity.VECTOR_REDIRECT_URL, + deviceId = state.deviceId, + providerId = null + ) + ?.let { prefetchUrl(it) } } } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt index 503b6d74a6..803fd38983 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt @@ -360,6 +360,9 @@ open class LoginActivity : VectorBaseActivity(), ToolbarCo private const val EXTRA_CONFIG = "EXTRA_CONFIG" + // Note that the domain can be displayed to the user for confirmation that he trusts it. So use a human readable string + const val VECTOR_REDIRECT_URL = "element://connect" + fun newIntent(context: Context, loginConfig: LoginConfig?): Intent { return Intent(context, LoginActivity::class.java).apply { putExtra(EXTRA_CONFIG, loginConfig) diff --git a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt index c396e61b1a..3b22e0f206 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt @@ -193,7 +193,12 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment if (state.loginMode is LoginMode.Sso) { - openInCustomTab(state.getSsoUrl(null)) + loginViewModel.getSsoUrl( + redirectUrl = LoginActivity.VECTOR_REDIRECT_URL, + deviceId = state.deviceId, + providerId = null + ) + ?.let { openInCustomTab(it) } } else { loginViewModel.handle(LoginAction.UpdateSignMode(SignMode.SignUp)) } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 0a6dbcaae2..7bf0b98841 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -26,8 +26,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.configureAndStart @@ -68,7 +69,7 @@ class LoginViewModel @AssistedInject constructor( private val homeServerHistoryService: HomeServerHistoryService ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: LoginViewState): LoginViewModel } @@ -810,12 +811,19 @@ class LoginViewModel @AssistedInject constructor( } override fun onCleared() { - super.onCleared() - currentTask?.cancel() + super.onCleared() } fun getInitialHomeServerUrl(): String? { return loginConfig?.homeServerUrl } + + fun getSsoUrl(redirectUrl: String, deviceId: String?, providerId: String?): String? { + return authenticationService.getSsoUrl(redirectUrl, deviceId, providerId) + } + + fun getFallbackUrl(forSignIn: Boolean, deviceId: String?): String? { + return authenticationService.getFallbackUrl(forSignIn, deviceId) + } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewState.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewState.kt index 5254abf1d9..37ac89794f 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewState.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewState.kt @@ -22,10 +22,6 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.PersistState import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.core.extensions.appendParamToUrl -import org.matrix.android.sdk.api.auth.MSC2858_SSO_REDIRECT_PATH -import org.matrix.android.sdk.api.auth.SSO_REDIRECT_PATH -import org.matrix.android.sdk.api.auth.SSO_REDIRECT_URL_PARAM data class LoginViewState( val asyncLoginAction: Async = Uninitialized, @@ -69,27 +65,4 @@ data class LoginViewState( fun isUserLogged(): Boolean { return asyncLoginAction is Success } - - fun getSsoUrl(providerId: String?): String { - return buildString { - append(homeServerUrl?.trim { it == '/' }) - if (providerId != null) { - append(MSC2858_SSO_REDIRECT_PATH) - append("/$providerId") - } else { - append(SSO_REDIRECT_PATH) - } - // Set a redirect url we will intercept later - appendParamToUrl(SSO_REDIRECT_URL_PARAM, VECTOR_REDIRECT_URL) - deviceId?.takeIf { it.isNotBlank() }?.let { - // But https://github.com/matrix-org/synapse/issues/5755 - appendParamToUrl("device_id", it) - } - } - } - - companion object { - // Note that the domain can be displayed to the user for confirmation that he trusts it. So use a human readable string - private const val VECTOR_REDIRECT_URL = "element://connect" - } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt index acf4f706c5..4b03c93321 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt @@ -33,14 +33,11 @@ import android.webkit.WebViewClient import androidx.appcompat.app.AlertDialog import com.airbnb.mvrx.activityViewModel import im.vector.app.R -import im.vector.app.core.extensions.appendParamToUrl import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginWebBinding import im.vector.app.features.signout.soft.SoftLogoutAction import im.vector.app.features.signout.soft.SoftLogoutViewModel -import org.matrix.android.sdk.api.auth.LOGIN_FALLBACK_PATH -import org.matrix.android.sdk.api.auth.REGISTER_FALLBACK_PATH import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber @@ -119,19 +116,7 @@ class LoginWebFragment @Inject constructor( } private fun launchWebView(state: LoginViewState) { - val url = buildString { - append(state.homeServerUrl?.trim { it == '/' }) - if (state.signMode == SignMode.SignIn) { - append(LOGIN_FALLBACK_PATH) - state.deviceId?.takeIf { it.isNotBlank() }?.let { - // But https://github.com/matrix-org/synapse/issues/5755 - appendParamToUrl("device_id", it) - } - } else { - // MODE_REGISTER - append(REGISTER_FALLBACK_PATH) - } - } + val url = loginViewModel.getFallbackUrl(state.signMode == SignMode.SignIn, state.deviceId) ?: return views.loginWebWebView.loadUrl(url) diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt index 6e8a530c9a..207256c75a 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -50,7 +51,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( private val stringProvider: StringProvider, private val rawService: RawService) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: MatrixToBottomSheetState): MatrixToBottomSheetViewModel } diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt index 75c7912646..1c0d859fa9 100644 --- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt @@ -33,12 +33,12 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.ORIENTATION import com.github.piasy.biv.view.BigImageView import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideRequest import im.vector.app.core.glide.GlideRequests import im.vector.app.core.ui.model.Size import im.vector.app.core.utils.DimensionConverter -import im.vector.app.core.utils.isLocalFile import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.content.ContentUrlResolver @@ -59,7 +59,8 @@ interface AttachmentData : Parcelable { val allowNonMxcUrls: Boolean } -class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, +class ImageContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper, + private val activeSessionHolder: ActiveSessionHolder, private val dimensionConverter: DimensionConverter) { @Parcelize @@ -73,7 +74,6 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: val maxHeight: Int, val width: Int?, val maxWidth: Int, - val isLocalFile: Boolean = url.isLocalFile(), // If true will load non mxc url, be careful to set it only for images sent by you override val allowNonMxcUrls: Boolean = false ) : AttachmentData @@ -291,7 +291,7 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: private fun resolveUrl(data: Data) = (activeSessionHolder.getActiveSession().contentUrlResolver().resolveFullSize(data.url) - ?: data.url?.takeIf { data.isLocalFile && data.allowNonMxcUrls }) + ?: data.url?.takeIf { localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls }) private fun processSize(data: Data, mode: Mode): Size { val maxImageWidth = data.maxWidth diff --git a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt index c771eece8f..7e4ea15ff0 100644 --- a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt @@ -24,7 +24,7 @@ import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.ErrorFormatter -import im.vector.app.core.utils.isLocalFile +import im.vector.app.core.files.LocalFilesHelper import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt @@ -33,7 +33,8 @@ import java.io.File import java.net.URLEncoder import javax.inject.Inject -class VideoContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, +class VideoContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper, + private val activeSessionHolder: ActiveSessionHolder, private val errorFormatter: ErrorFormatter) { @Parcelize @@ -63,7 +64,7 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder: loadingView.isVisible = false errorView.isVisible = true errorView.setText(R.string.unknown_error) - } else if (data.url.isLocalFile() && data.allowNonMxcUrls) { + } else if (localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls) { thumbnailView.isVisible = false loadingView.isVisible = false videoView.isVisible = true @@ -98,7 +99,7 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder: } } else { val resolvedUrl = contentUrlResolver.resolveFullSize(data.url) - ?: data.url?.takeIf { data.url.isLocalFile() && data.allowNonMxcUrls } + ?: data.url?.takeIf { localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls } if (resolvedUrl == null) { thumbnailView.isVisible = false diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultViewModel.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultViewModel.kt index 98b729603a..ac7aee797a 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultViewModel.kt @@ -19,8 +19,9 @@ import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.reactions.data.EmojiDataSource @@ -36,7 +37,7 @@ class EmojiSearchResultViewModel @AssistedInject constructor( private val dataSource: EmojiDataSource) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: EmojiSearchResultViewState): EmojiSearchResultViewModel } diff --git a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt index 868a4e4dd6..c8b0037311 100644 --- a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -48,7 +49,7 @@ class RequireActiveMembershipViewModel @AssistedInject constructor( private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RequireActiveMembershipViewState): RequireActiveMembershipViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryViewModel.kt index c58e255bcc..f5c545c34d 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryViewModel.kt @@ -23,8 +23,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.appendAt -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.extensions.orFalse @@ -46,7 +47,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: PublicRoomsViewState): RoomDirectoryViewModel } @@ -221,7 +222,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: } override fun onCleared() { - super.onCleared() currentTask?.cancel() + super.onCleared() } } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt index 216a016fbe..3c027c4845 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.raw.wellknown.getElementWellknown @@ -46,7 +47,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: Cr private val rawService: RawService ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: CreateRoomViewState): CreateRoomViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt index 44044304bc..5460411907 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.MatrixCallback @@ -33,7 +34,7 @@ class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initial private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomDirectoryPickerViewState): RoomDirectoryPickerViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt index 72c4c58a42..c99213d890 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -46,7 +47,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted private val ini private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomPreviewViewState): RoomPreviewViewModel } @@ -84,22 +85,34 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted private val ini when (peekResult) { is PeekResult.Success -> { setState { + // Do not override what we had from the permalink + val newHomeServers = if (homeServers.isEmpty()) { + peekResult.viaServers.take(3) + } else { + homeServers + } copy( roomId = peekResult.roomId, avatarUrl = peekResult.avatarUrl, roomAlias = peekResult.alias ?: initialState.roomAlias, roomTopic = peekResult.topic, - homeServers = peekResult.viaServers, + homeServers = newHomeServers, peekingState = Success(PeekingState.FOUND) ) } } is PeekResult.PeekingNotAllowed -> { setState { + // Do not override what we had from the permalink + val newHomeServers = if (homeServers.isEmpty()) { + peekResult.viaServers.take(3) + } else { + homeServers + } copy( roomId = peekResult.roomId, roomAlias = peekResult.alias ?: initialState.roomAlias, - homeServers = peekResult.viaServers, + homeServers = newHomeServers, peekingState = Success(PeekingState.NO_ACCESS) ) } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 3c0ff15fb8..92cdf305fe 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -366,7 +366,7 @@ class RoomMemberProfileFragment @Inject constructor( } override fun onEditPowerLevel(currentRole: Role) { - EditPowerLevelDialogs.showChoice(requireActivity(), currentRole) { newPowerLevel -> + EditPowerLevelDialogs.showChoice(requireActivity(), R.string.power_level_edit_title, currentRole) { newPowerLevel -> viewModel.handle(RoomMemberProfileAction.SetPowerLevel(currentRole.value, newPowerLevel, true)) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 39b5884308..0556b9d2d6 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider @@ -61,7 +62,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomMemberProfileViewState): RoomMemberProfileViewModel } @@ -162,11 +163,13 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v } else if (action.askForValidation && state.isMine) { _viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelDemoteWarning(action.previousValue, action.newValue)) } else { - currentPowerLevelsContent.setUserPowerLevel(state.userId, action.newValue) + val newPowerLevelsContent = currentPowerLevelsContent + .setUserPowerLevel(state.userId, action.newValue) + .toContent() viewModelScope.launch { _viewEvents.post(RoomMemberProfileViewEvents.Loading()) try { - room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, currentPowerLevelsContent.toContent()) + room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, newPowerLevelsContent) _viewEvents.post(RoomMemberProfileViewEvents.OnSetPowerLevelSuccess) } catch (failure: Throwable) { _viewEvents.post(RoomMemberProfileViewEvents.Failure(failure)) diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt index 0f1ac3bfea..7d31a5c811 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.HasScreenInjector import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -48,7 +49,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: DeviceListViewState, args: DeviceListBottomSheet.Args): DeviceListBottomSheetViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt index 4316a4bd0d..764271f7ce 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt @@ -19,6 +19,7 @@ package im.vector.app.features.roommemberprofile.powerlevel import android.app.Activity import android.content.DialogInterface import android.view.KeyEvent +import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import im.vector.app.R @@ -29,7 +30,10 @@ import org.matrix.android.sdk.api.session.room.powerlevels.Role object EditPowerLevelDialogs { - fun showChoice(activity: Activity, currentRole: Role, listener: (Int) -> Unit) { + fun showChoice(activity: Activity, + @StringRes titleRes: Int, + currentRole: Role, + listener: (Int) -> Unit) { val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_edit_power_level, null) val views = DialogEditPowerLevelBinding.bind(dialogLayout) views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId -> @@ -45,7 +49,7 @@ object EditPowerLevelDialogs { } AlertDialog.Builder(activity) - .setTitle(R.string.power_level_edit_title) + .setTitle(titleRes) .setView(dialogLayout) .setPositiveButton(R.string.edit) { _, _ -> val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt index 76649d53b3..7cb713d378 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt @@ -27,6 +27,7 @@ import im.vector.app.R import im.vector.app.core.di.ScreenComponent import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragmentToBackstack +import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.ToolbarConfigurable import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivitySimpleBinding @@ -38,6 +39,7 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment import im.vector.app.features.roomprofile.members.RoomMemberListFragment import im.vector.app.features.roomprofile.settings.RoomSettingsFragment import im.vector.app.features.roomprofile.alias.RoomAliasFragment +import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import javax.inject.Inject @@ -102,12 +104,13 @@ class RoomProfileActivity : .observe() .subscribe { sharedAction -> when (sharedAction) { - is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers() - is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings() - is RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias() - is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads() - is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers() - } + RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers() + RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings() + RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias() + RoomProfileSharedAction.OpenRoomPermissionsSettings -> openRoomPermissions() + RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads() + RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers() + }.exhaustive } .disposeOnDestroy() @@ -144,6 +147,10 @@ class RoomProfileActivity : addFragmentToBackstack(R.id.simpleFragmentContainer, RoomAliasFragment::class.java, roomProfileArgs) } + private fun openRoomPermissions() { + addFragmentToBackstack(R.id.simpleFragmentContainer, RoomPermissionsFragment::class.java, roomProfileArgs) + } + private fun openRoomMembers() { addFragmentToBackstack(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index 891d15d04f..6b988df94d 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -26,6 +26,8 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.ShortcutCreator +import im.vector.app.features.home.room.detail.timeline.TimelineEventController +import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.settings.VectorPreferences import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -53,6 +55,7 @@ class RoomProfileController @Inject constructor( fun onSettingsClicked() fun onLeaveRoomClicked() fun onRoomIdClicked() + fun onUrlInTopicLongClicked(url: String) } override fun buildModels(data: RoomProfileViewState?) { @@ -71,6 +74,16 @@ class RoomProfileController @Inject constructor( id("topic") content(it) maxLines(2) + movementMethod(createLinkMovementMethod(object : TimelineEventController.UrlClickCallback { + override fun onUrlClicked(url: String, title: String): Boolean { + return false + } + + override fun onUrlLongClicked(url: String): Boolean { + callback?.onUrlInTopicLongClicked(url) + return true + } + })) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 473c1d4324..58fd78e26a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -17,6 +17,7 @@ package im.vector.app.features.roomprofile +import android.content.DialogInterface import android.os.Bundle import android.os.Parcelable import android.view.LayoutInflater @@ -34,6 +35,7 @@ import com.airbnb.mvrx.withState import im.vector.app.R import im.vector.app.core.animations.AppBarStateChangeListener import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener +import im.vector.app.core.dialogs.withColoredButton import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.copyOnLongClick @@ -247,20 +249,37 @@ class RoomProfileFragment @Inject constructor( } override fun onLeaveRoomClicked() { + val isPublicRoom = roomProfileViewModel.isPublicRoom() + val message = buildString { + append(getString(R.string.room_participants_leave_prompt_msg)) + if (!isPublicRoom) { + append("\n\n") + append(getString(R.string.room_participants_leave_private_warning)) + } + } AlertDialog.Builder(requireContext()) .setTitle(R.string.room_participants_leave_prompt_title) - .setMessage(R.string.room_participants_leave_prompt_msg) + .setMessage(message) .setPositiveButton(R.string.leave) { _, _ -> roomProfileViewModel.handle(RoomProfileAction.LeaveRoom) } .setNegativeButton(R.string.cancel, null) .show() + .apply { + if (!isPublicRoom) { + withColoredButton(DialogInterface.BUTTON_POSITIVE) + } + } } override fun onRoomIdClicked() { copyToClipboard(requireContext(), roomProfileArgs.roomId) } + override fun onUrlInTopicLongClicked(url: String) { + copyToClipboard(requireContext(), url, true) + } + private fun onShareRoomProfile(permalink: String) { startSharePlainTextIntent( fragment = this, diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt index 83a610cf1b..2a5775d1af 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileSharedAction.kt @@ -24,6 +24,7 @@ import im.vector.app.core.platform.VectorSharedAction sealed class RoomProfileSharedAction : VectorSharedAction { object OpenRoomSettings : RoomProfileSharedAction() object OpenRoomAliasesSettings : RoomProfileSharedAction() + object OpenRoomPermissionsSettings : RoomProfileSharedAction() object OpenRoomUploads : RoomProfileSharedAction() object OpenRoomMembers : RoomProfileSharedAction() object OpenBannedRoomMembers : RoomProfileSharedAction() diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt index ec772ffcaa..02a648287f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt @@ -21,8 +21,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -37,6 +38,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper +import org.matrix.android.sdk.api.session.room.state.isPublic import org.matrix.android.sdk.rx.RxRoom import org.matrix.android.sdk.rx.rx import org.matrix.android.sdk.rx.unwrap @@ -48,7 +50,7 @@ class RoomProfileViewModel @AssistedInject constructor( private val session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomProfileViewState): RoomProfileViewModel } @@ -109,6 +111,10 @@ class RoomProfileViewModel @AssistedInject constructor( }.exhaustive } + fun isPublicRoom(): Boolean { + return room.isPublic() + } + private fun handleEnableEncryption() { postLoading(true) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt index f470eeefc2..8832c9f7d8 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.powerlevel.PowerLevelsObservableFactory @@ -44,7 +45,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomAliasViewState): RoomAliasViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetViewModel.kt index 7f723cae53..e762b52025 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetViewModel.kt @@ -18,8 +18,9 @@ package im.vector.app.features.roomprofile.alias.detail import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -30,7 +31,7 @@ class RoomAliasBottomSheetViewModel @AssistedInject constructor( session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomAliasBottomSheetState): RoomAliasBottomSheetViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt index 0cecd22fa0..5663392c6c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt @@ -20,8 +20,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel @@ -47,7 +48,7 @@ class RoomBannedMemberListViewModel @AssistedInject constructor(@Assisted initia private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomBannedMemberListViewState): RoomBannedMemberListViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt index 9f15e62b3b..de983537fc 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt @@ -20,8 +20,9 @@ import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -53,7 +54,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomMemberListViewState): RoomMemberListViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt new file mode 100644 index 0000000000..bb1054b704 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 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.roomprofile.permissions + +import androidx.annotation.StringRes +import im.vector.app.R +import org.matrix.android.sdk.api.session.events.model.EventType + +/** + * Change on each permission has an effect on the power level event. Try to sort the effect by category. + */ +sealed class EditablePermission(@StringRes val labelResId: Int) { + // Updates `content.events.[eventType]` + open class EventTypeEditablePermission(val eventType: String, @StringRes labelResId: Int) : EditablePermission(labelResId) + + class ModifyWidgets : EventTypeEditablePermission( + // Note: Element Web still use legacy value + EventType.STATE_ROOM_WIDGET_LEGACY, + R.string.room_permissions_modify_widgets + ) + + class ChangeRoomAvatar : EventTypeEditablePermission( + EventType.STATE_ROOM_AVATAR, + R.string.room_permissions_change_room_avatar + ) + + class ChangeMainAddressForTheRoom : EventTypeEditablePermission( + EventType.STATE_ROOM_CANONICAL_ALIAS, + R.string.room_permissions_change_main_address_for_the_room + ) + + class EnableRoomEncryption : EventTypeEditablePermission( + EventType.STATE_ROOM_ENCRYPTION, + R.string.room_permissions_enable_room_encryption + ) + + class ChangeHistoryVisibility : EventTypeEditablePermission( + EventType.STATE_ROOM_HISTORY_VISIBILITY, + R.string.room_permissions_change_history_visibility + ) + + class ChangeRoomName : EventTypeEditablePermission( + EventType.STATE_ROOM_NAME, + R.string.room_permissions_change_room_name + ) + + class ChangePermissions : EventTypeEditablePermission( + EventType.STATE_ROOM_POWER_LEVELS, + R.string.room_permissions_change_permissions + ) + + class SendRoomServerAclEvents : EventTypeEditablePermission( + EventType.STATE_ROOM_SERVER_ACL, + R.string.room_permissions_send_m_room_server_acl_events + ) + + class UpgradeTheRoom : EventTypeEditablePermission( + EventType.STATE_ROOM_TOMBSTONE, + R.string.room_permissions_upgrade_the_room + ) + + class ChangeTopic : EventTypeEditablePermission( + EventType.STATE_ROOM_TOPIC, + R.string.room_permissions_change_topic + ) + + // Updates `content.users_default` + class DefaultRole : EditablePermission(R.string.room_permissions_default_role) + + // Updates `content.events_default` + class SendMessages : EditablePermission(R.string.room_permissions_send_messages) + + // Updates `content.invites` + class InviteUsers : EditablePermission(R.string.room_permissions_invite_users) + + // Updates `content.state_default` + class ChangeSettings : EditablePermission(R.string.room_permissions_change_settings) + + // Updates `content.kick` + class KickUsers : EditablePermission(R.string.room_permissions_kick_users) + + // Updates `content.ban` + class BanUsers : EditablePermission(R.string.room_permissions_ban_users) + + // Updates `content.redact` + class RemoveMessagesSentByOthers : EditablePermission(R.string.room_permissions_remove_messages_sent_by_others) + + // Updates `content.notification.room` + class NotifyEveryone : EditablePermission(R.string.room_permissions_notify_everyone) +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsAction.kt new file mode 100644 index 0000000000..b853dda160 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsAction.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class RoomPermissionsAction : VectorViewModelAction { + object ToggleShowAllPermissions : RoomPermissionsAction() + + data class UpdatePermission(val editablePermission: EditablePermission, val powerLevel: Int) : RoomPermissionsAction() +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt new file mode 100644 index 0000000000..92bdac7ae0 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt @@ -0,0 +1,176 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import com.airbnb.epoxy.TypedEpoxyController +import com.airbnb.mvrx.Success +import im.vector.app.R +import im.vector.app.core.epoxy.loadingItem +import im.vector.app.core.epoxy.profiles.buildProfileAction +import im.vector.app.core.epoxy.profiles.buildProfileSection +import im.vector.app.core.resources.ColorProvider +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.discovery.settingsInfoItem +import im.vector.app.features.form.formAdvancedToggleItem +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.powerlevels.Role +import javax.inject.Inject + +class RoomPermissionsController @Inject constructor( + private val stringProvider: StringProvider, + colorProvider: ColorProvider +) : TypedEpoxyController() { + + interface Callback { + fun onEditPermission(editablePermission: EditablePermission, currentRole: Role) + fun toggleShowAllPermissions() + } + + var callback: Callback? = null + + private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color) + + // Order is the order applied in the UI + // Element Web order is not really nice, try to put the settings which are more likely to be updated first + // And a second section, hidden by default + private val usefulEditablePermissions = listOf( + EditablePermission.ChangeRoomAvatar(), + EditablePermission.ChangeRoomName(), + EditablePermission.ChangeTopic() + ) + + private val advancedEditablePermissions = listOf( + EditablePermission.ChangeMainAddressForTheRoom(), + + EditablePermission.DefaultRole(), + EditablePermission.InviteUsers(), + EditablePermission.KickUsers(), + EditablePermission.BanUsers(), + + EditablePermission.SendMessages(), + + EditablePermission.RemoveMessagesSentByOthers(), + EditablePermission.NotifyEveryone(), + + EditablePermission.ChangeSettings(), + EditablePermission.ModifyWidgets(), + EditablePermission.ChangeHistoryVisibility(), + EditablePermission.ChangePermissions(), + EditablePermission.SendRoomServerAclEvents(), + EditablePermission.EnableRoomEncryption(), + EditablePermission.UpgradeTheRoom() + ) + + init { + setData(null) + } + + override fun buildModels(data: RoomPermissionsViewState?) { + buildProfileSection( + stringProvider.getString(R.string.room_permissions_title) + ) + + when (val content = data?.currentPowerLevelsContent) { + is Success -> buildPermissions(data, content()) + else -> { + loadingItem { + id("loading") + loadingText(stringProvider.getString(R.string.loading)) + } + } + } + } + + private fun buildPermissions(data: RoomPermissionsViewState, content: PowerLevelsContent) { + val editable = data.actionPermissions.canChangePowerLevels + settingsInfoItem { + id("notice") + helperText(stringProvider.getString(if (editable) R.string.room_permissions_notice else R.string.room_permissions_notice_read_only)) + } + + // Useful permissions + usefulEditablePermissions.forEach { buildPermission(it, content, editable) } + + // Toggle + formAdvancedToggleItem { + id("showAdvanced") + title(stringProvider.getString(if (data.showAdvancedPermissions) R.string.hide_advanced else R.string.show_advanced)) + expanded(!data.showAdvancedPermissions) + listener { callback?.toggleShowAllPermissions() } + } + + // Advanced permissions + if (data.showAdvancedPermissions) { + advancedEditablePermissions.forEach { buildPermission(it, content, editable) } + } + } + + private fun buildPermission(editablePermission: EditablePermission, content: PowerLevelsContent, editable: Boolean) { + val currentRole = getCurrentRole(editablePermission, content) + buildProfileAction( + id = editablePermission.labelResId.toString(), + title = stringProvider.getString(editablePermission.labelResId), + subtitle = getSubtitle(currentRole), + dividerColor = dividerColor, + divider = true, + editable = editable, + action = { + callback + ?.takeIf { editable } + ?.onEditPermission(editablePermission, currentRole) + } + ) + } + + private fun getSubtitle(currentRole: Role): String { + return when (currentRole) { + Role.Admin, + Role.Moderator, + Role.Default -> stringProvider.getString(currentRole.res) + is Role.Custom -> stringProvider.getString(currentRole.res, currentRole.value) + } + } + + private fun getCurrentRole(editablePermission: EditablePermission, content: PowerLevelsContent): Role { + val value = when (editablePermission) { + is EditablePermission.EventTypeEditablePermission -> content.events[editablePermission.eventType] ?: content.stateDefault + is EditablePermission.DefaultRole -> content.usersDefault + is EditablePermission.SendMessages -> content.eventsDefault + is EditablePermission.InviteUsers -> content.invite + is EditablePermission.ChangeSettings -> content.stateDefault + is EditablePermission.KickUsers -> content.kick + is EditablePermission.BanUsers -> content.ban + is EditablePermission.RemoveMessagesSentByOthers -> content.redact + is EditablePermission.NotifyEveryone -> content.notificationLevel(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY) + } + + return Role.fromValue( + value, + when (editablePermission) { + is EditablePermission.EventTypeEditablePermission -> content.stateDefault + is EditablePermission.DefaultRole -> Role.Default.value + is EditablePermission.SendMessages -> Role.Default.value + is EditablePermission.InviteUsers -> Role.Moderator.value + is EditablePermission.ChangeSettings -> Role.Moderator.value + is EditablePermission.KickUsers -> Role.Moderator.value + is EditablePermission.BanUsers -> Role.Moderator.value + is EditablePermission.RemoveMessagesSentByOthers -> Role.Moderator.value + is EditablePermission.NotifyEveryone -> Role.Moderator.value + } + ) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt new file mode 100644 index 0000000000..61635c9b31 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.airbnb.mvrx.args +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import im.vector.app.R +import im.vector.app.core.extensions.cleanup +import im.vector.app.core.extensions.configureWith +import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.utils.toast +import im.vector.app.databinding.FragmentRoomSettingGenericBinding +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs +import im.vector.app.features.roomprofile.RoomProfileArgs +import org.matrix.android.sdk.api.session.room.powerlevels.Role +import org.matrix.android.sdk.api.util.toMatrixItem +import javax.inject.Inject + +class RoomPermissionsFragment @Inject constructor( + val viewModelFactory: RoomPermissionsViewModel.Factory, + private val controller: RoomPermissionsController, + private val avatarRenderer: AvatarRenderer +) : + VectorBaseFragment(), + RoomPermissionsController.Callback { + + private val viewModel: RoomPermissionsViewModel by fragmentViewModel() + + private val roomProfileArgs: RoomProfileArgs by args() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomSettingGenericBinding { + return FragmentRoomSettingGenericBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + controller.callback = this + setupToolbar(views.roomSettingsToolbar) + views.roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true) + views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.isVisible = true + + viewModel.observeViewEvents { + when (it) { + is RoomPermissionsViewEvents.Failure -> showFailure(it.throwable) + RoomPermissionsViewEvents.Success -> showSuccess() + }.exhaustive + } + } + + private fun showSuccess() { + activity?.toast(R.string.room_settings_save_success) + } + + override fun onDestroyView() { + controller.callback = null + views.roomSettingsRecyclerView.cleanup() + super.onDestroyView() + } + + override fun invalidate() = withState(viewModel) { state -> + views.waitingView.root.isVisible = state.isLoading + controller.setData(state) + renderRoomSummary(state) + } + + private fun renderRoomSummary(state: RoomPermissionsViewState) { + state.roomSummary()?.let { + views.roomSettingsToolbarTitleView.text = it.displayName + avatarRenderer.render(it.toMatrixItem(), views.roomSettingsToolbarAvatarImageView) + } + } + + override fun onEditPermission(editablePermission: EditablePermission, currentRole: Role) { + EditPowerLevelDialogs.showChoice(requireActivity(), editablePermission.labelResId, currentRole) { newPowerLevel -> + viewModel.handle(RoomPermissionsAction.UpdatePermission(editablePermission, newPowerLevel)) + } + } + + override fun toggleShowAllPermissions() { + viewModel.handle(RoomPermissionsAction.ToggleShowAllPermissions) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewEvents.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewEvents.kt new file mode 100644 index 0000000000..8994398cf3 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewEvents.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import im.vector.app.core.platform.VectorViewEvents + +/** + * Transient events for room settings screen + */ +sealed class RoomPermissionsViewEvents : VectorViewEvents { + data class Failure(val throwable: Throwable) : RoomPermissionsViewEvents() + object Success : RoomPermissionsViewEvents() +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt new file mode 100644 index 0000000000..626c20010c --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt @@ -0,0 +1,153 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import androidx.lifecycle.viewModelScope +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.ViewModelContext +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory +import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.powerlevel.PowerLevelsObservableFactory +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper +import org.matrix.android.sdk.rx.rx +import org.matrix.android.sdk.rx.unwrap + +class RoomPermissionsViewModel @AssistedInject constructor(@Assisted initialState: RoomPermissionsViewState, + private val session: Session) + : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory { + fun create(initialState: RoomPermissionsViewState): RoomPermissionsViewModel + } + + companion object : MvRxViewModelFactory { + + @JvmStatic + override fun create(viewModelContext: ViewModelContext, state: RoomPermissionsViewState): RoomPermissionsViewModel? { + val fragment: RoomPermissionsFragment = (viewModelContext as FragmentViewModelContext).fragment() + return fragment.viewModelFactory.create(state) + } + } + + private val room = session.getRoom(initialState.roomId)!! + + init { + observeRoomSummary() + observePowerLevel() + } + + private fun observeRoomSummary() { + room.rx().liveRoomSummary() + .unwrap() + .execute { async -> + copy( + roomSummary = async + ) + } + } + + private fun observePowerLevel() { + PowerLevelsObservableFactory(room) + .createObservable() + .subscribe { powerLevelContent -> + val powerLevelsHelper = PowerLevelsHelper(powerLevelContent) + val permissions = RoomPermissionsViewState.ActionPermissions( + canChangePowerLevels = powerLevelsHelper.isUserAllowedToSend( + userId = session.myUserId, + isState = true, + eventType = EventType.STATE_ROOM_POWER_LEVELS + ) + ) + setState { + copy( + actionPermissions = permissions, + currentPowerLevelsContent = Success(powerLevelContent) + ) + } + } + .disposeOnClear() + } + + override fun handle(action: RoomPermissionsAction) { + when (action) { + is RoomPermissionsAction.UpdatePermission -> updatePermission(action) + RoomPermissionsAction.ToggleShowAllPermissions -> toggleShowAllPermissions() + }.exhaustive + } + + private fun toggleShowAllPermissions() { + setState { + copy(showAdvancedPermissions = !showAdvancedPermissions) + } + } + + private fun updatePermission(action: RoomPermissionsAction.UpdatePermission) { + withState { state -> + val currentPowerLevel = state.currentPowerLevelsContent.invoke() ?: return@withState + postLoading(true) + viewModelScope.launch { + try { + val newPowerLevelsContent = when (action.editablePermission) { + is EditablePermission.EventTypeEditablePermission -> currentPowerLevel.copy( + events = currentPowerLevel.events.toMutableMap().apply { + put(action.editablePermission.eventType, action.powerLevel) + } + ) + is EditablePermission.DefaultRole -> currentPowerLevel.copy(usersDefault = action.powerLevel) + is EditablePermission.SendMessages -> currentPowerLevel.copy(eventsDefault = action.powerLevel) + is EditablePermission.InviteUsers -> currentPowerLevel.copy(invite = action.powerLevel) + is EditablePermission.ChangeSettings -> currentPowerLevel.copy(stateDefault = action.powerLevel) + is EditablePermission.KickUsers -> currentPowerLevel.copy(kick = action.powerLevel) + is EditablePermission.BanUsers -> currentPowerLevel.copy(ban = action.powerLevel) + is EditablePermission.RemoveMessagesSentByOthers -> currentPowerLevel.copy(redact = action.powerLevel) + is EditablePermission.NotifyEveryone -> currentPowerLevel.copy( + notifications = currentPowerLevel.notifications.toMutableMap().apply { + put(PowerLevelsContent.NOTIFICATIONS_ROOM_KEY, action.powerLevel) + } + ) + } + room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, newPowerLevelsContent.toContent()) + setState { + copy( + isLoading = false + ) + } + } catch (failure: Throwable) { + postLoading(false) + _viewEvents.post(RoomPermissionsViewEvents.Failure(failure)) + } + } + } + } + + private fun postLoading(isLoading: Boolean) { + setState { + copy(isLoading = isLoading) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewState.kt new file mode 100644 index 0000000000..ce38ab87e5 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewState.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2021 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.roomprofile.permissions + +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.Uninitialized +import im.vector.app.features.roomprofile.RoomProfileArgs +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.model.RoomSummary + +data class RoomPermissionsViewState( + val roomId: String, + val roomSummary: Async = Uninitialized, + val actionPermissions: ActionPermissions = ActionPermissions(), + val showAdvancedPermissions: Boolean = false, + val currentPowerLevelsContent: Async = Uninitialized, + val isLoading: Boolean = false +) : MvRxState { + + constructor(args: RoomProfileArgs) : this(roomId = args.roomId) + + data class ActionPermissions( + val canChangePowerLevels: Boolean = false + ) +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt index bf3c1f87f8..1984be078d 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt @@ -46,6 +46,7 @@ class RoomSettingsController @Inject constructor( fun onTopicChanged(topic: String) fun onHistoryVisibilityClicked() fun onRoomAliasesClicked() + fun onRoomPermissionsClicked() fun onJoinRuleClicked() } @@ -115,6 +116,16 @@ class RoomSettingsController @Inject constructor( action = { callback?.onRoomAliasesClicked() } ) + buildProfileAction( + id = "permissions", + title = stringProvider.getString(R.string.room_settings_permissions_title), + subtitle = stringProvider.getString(R.string.room_settings_permissions_subtitle), + dividerColor = dividerColor, + divider = true, + editable = true, + action = { callback?.onRoomPermissionsClicked() } + ) + buildProfileAction( id = "historyReadability", title = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_title), diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt index 52e273f3d4..1ca539ea7e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt @@ -178,6 +178,10 @@ class RoomSettingsFragment @Inject constructor( roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomAliasesSettings) } + override fun onRoomPermissionsClicked() { + roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomPermissionsSettings) + } + override fun onJoinRuleClicked() = withState(viewModel) { state -> val currentJoinRule = state.newRoomJoinRules.newJoinRules ?: state.currentRoomJoinRules val currentGuestAccess = state.newRoomJoinRules.newGuestAccess ?: state.currentGuestAccess diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt index 48ff38f92e..bf227ea5e8 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt @@ -20,8 +20,9 @@ import androidx.core.net.toFile import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.powerlevel.PowerLevelsObservableFactory @@ -45,7 +46,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomSettingsViewState): RoomSettingsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt index b62b633a36..cdf139c7f6 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch @@ -41,7 +42,7 @@ class RoomUploadsViewModel @AssistedInject constructor( private val session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomUploadsViewState): RoomUploadsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 16be2b1552..d3ef36a80b 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -98,6 +98,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val SETTINGS_VIBRATE_ON_MENTION_KEY = "SETTINGS_VIBRATE_ON_MENTION_KEY" private const val SETTINGS_SEND_MESSAGE_WITH_ENTER = "SETTINGS_SEND_MESSAGE_WITH_ENTER" private const val SETTINGS_ENABLE_CHAT_EFFECTS = "SETTINGS_ENABLE_CHAT_EFFECTS" + private const val SETTINGS_SHOW_EMOJI_KEYBOARD = "SETTINGS_SHOW_EMOJI_KEYBOARD" // Help private const val SETTINGS_SHOULD_SHOW_HELP_ON_ROOM_LIST_KEY = "SETTINGS_SHOULD_SHOW_HELP_ON_ROOM_LIST_KEY" @@ -207,6 +208,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY, SETTINGS_SEND_MESSAGE_WITH_ENTER, + SETTINGS_SHOW_EMOJI_KEYBOARD, SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY, SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY, @@ -822,6 +824,15 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_SEND_MESSAGE_WITH_ENTER, false) } + /** + * Tells if the emoji keyboard button should be visible or not. + * + * @return true to show emoji keyboard button. + */ + fun showEmojiKeyboard(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_SHOW_EMOJI_KEYBOARD, true) + } + /** * Tells if the rage shake is used. * diff --git a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt index 211559c657..6a7084fb81 100644 --- a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt @@ -20,8 +20,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModelAction @@ -43,7 +44,7 @@ class DeactivateAccountViewModel @AssistedInject constructor(@Assisted private v private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: DeactivateAccountViewState): DeactivateAccountViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt index 3f70ac1fd7..fdf5d611fa 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt @@ -18,8 +18,9 @@ package im.vector.app.features.settings.crosssigning import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.VectorViewModel import io.reactivex.Observable import io.reactivex.functions.BiFunction @@ -57,7 +58,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: CrossSigningSettingsViewState): CrossSigningSettingsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt index ad840d2efb..ee5b0a6092 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt @@ -19,8 +19,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -33,7 +34,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As val session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: DeviceVerificationInfoBottomSheetViewState, deviceId: String): DeviceVerificationInfoBottomSheetViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 8c5762afce..eb034530ef 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -26,8 +26,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.error.SsoFlowNotSupportedYet import im.vector.app.core.platform.VectorViewModel import io.reactivex.Observable @@ -72,7 +73,7 @@ class DevicesViewModel @AssistedInject constructor( private val session: Session ) : VectorViewModel(initialState), VerificationService.Listener { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: DevicesViewState): DevicesViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt index af8d162f15..b2200e6a6d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt @@ -23,8 +23,9 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -63,7 +64,7 @@ class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: A } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: AccountDataViewState): AccountDataViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsPaperTrailViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsPaperTrailViewModel.kt index 4249ef09fa..325538ee5e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsPaperTrailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsPaperTrailViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -57,7 +58,7 @@ class GossipingEventsPaperTrailViewModel @AssistedInject constructor(@Assisted i override fun handle(action: EmptyAction) {} - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: GossipingEventsPaperTrailState): GossipingEventsPaperTrailViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt index 0b0b923a48..c0a791233f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -65,7 +66,7 @@ class KeyRequestListViewModel @AssistedInject constructor(@Assisted initialState override fun handle(action: EmptyAction) {} - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: KeyRequestListViewState): KeyRequestListViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt index a7d5e8f1ac..e7a56ef9df 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt @@ -27,8 +27,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewModel @@ -54,7 +55,7 @@ class KeyRequestViewModel @AssistedInject constructor( private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: KeyRequestViewState): KeyRequestViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt index 98c9f8e4f1..fdc6585829 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModelAction import org.matrix.android.sdk.api.MatrixCallback @@ -47,7 +48,7 @@ class IgnoredUsersViewModel @AssistedInject constructor(@Assisted initialState: private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: IgnoredUsersViewState): IgnoredUsersViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt index df7cc4ba84..2e59b0ef7d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.configuration.VectorConfiguration @@ -35,7 +36,7 @@ class LocalePickerViewModel @AssistedInject constructor( private val vectorConfiguration: VectorConfiguration ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: LocalePickerViewState): LocalePickerViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt index 2c8b902188..7981d71ce1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -39,7 +40,7 @@ class PushGatewaysViewModel @AssistedInject constructor(@Assisted initialState: private val session: Session) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: PushGatewayViewState): PushGatewaysViewModel } diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt index 41b6146bb1..65cfadb6a9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt @@ -23,8 +23,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.error.SsoFlowNotSupportedYet import im.vector.app.core.extensions.exhaustive @@ -89,7 +90,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor( } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ThreePidsSettingsViewState): ThreePidsSettingsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt index 9014565e08..4d211d11de 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt @@ -20,8 +20,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.toggle import im.vector.app.core.platform.VectorViewModel @@ -42,7 +43,7 @@ class IncomingShareViewModel @AssistedInject constructor( private val breadcrumbsRoomComparator: BreadcrumbsRoomComparator) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: IncomingShareViewState): IncomingShareViewModel } diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt index f1d9a66342..bebaa09063 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt @@ -23,8 +23,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.hasUnsavedKeys import im.vector.app.core.platform.VectorViewModel @@ -47,7 +48,7 @@ class SoftLogoutViewModel @AssistedInject constructor( private val authenticationService: AuthenticationService ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: SoftLogoutViewState): SoftLogoutViewModel } @@ -232,8 +233,7 @@ class SoftLogoutViewModel @AssistedInject constructor( } override fun onCleared() { - super.onCleared() - currentTask?.cancel() + super.onCleared() } } diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt index 89d6e970cc..4ecad80876 100644 --- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt @@ -22,8 +22,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch @@ -35,7 +36,7 @@ class ReviewTermsViewModel @AssistedInject constructor( private val session: Session ) : VectorViewModel(initialState) { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ReviewTermsViewState): ReviewTermsViewModel } diff --git a/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt b/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt index bba6b9c253..0856ac4b35 100644 --- a/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt +++ b/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt @@ -18,6 +18,8 @@ package im.vector.app.features.themes import android.app.Activity import android.content.Context +import android.content.res.Configuration +import android.content.res.Resources import android.graphics.drawable.Drawable import android.util.TypedValue import android.view.Menu @@ -39,10 +41,14 @@ object ThemeUtils { const val APPLICATION_THEME_KEY = "APPLICATION_THEME_KEY" // the theme possible values + private const val SYSTEM_THEME_VALUE = "system" private const val THEME_DARK_VALUE = "dark" private const val THEME_LIGHT_VALUE = "light" private const val THEME_BLACK_VALUE = "black" + // The default theme + private const val DEFAULT_THEME = SYSTEM_THEME_VALUE + private var currentTheme = AtomicReference(null) private val mColorByAttr = HashMap() @@ -54,13 +60,12 @@ object ThemeUtils { } /** - * @return true if current theme is Light or Status + * @return true if current theme is Light or current theme is System and system theme is light */ fun isLightTheme(context: Context): Boolean { - return when (getApplicationTheme(context)) { - THEME_LIGHT_VALUE -> true - else -> false - } + val theme = getApplicationTheme(context) + return theme == THEME_LIGHT_VALUE + || (theme == SYSTEM_THEME_VALUE && !isSystemDarkTheme(context.resources)) } /** @@ -73,11 +78,11 @@ object ThemeUtils { val currentTheme = this.currentTheme.get() return if (currentTheme == null) { val prefs = DefaultSharedPreferences.getInstance(context) - var themeFromPref = prefs.getString(APPLICATION_THEME_KEY, THEME_LIGHT_VALUE) ?: THEME_LIGHT_VALUE + var themeFromPref = prefs.getString(APPLICATION_THEME_KEY, DEFAULT_THEME) ?: DEFAULT_THEME if (themeFromPref == "status") { - // Migrate to light theme, which is the closest theme - themeFromPref = THEME_LIGHT_VALUE - prefs.edit { putString(APPLICATION_THEME_KEY, THEME_LIGHT_VALUE) } + // Migrate to the default theme + themeFromPref = DEFAULT_THEME + prefs.edit { putString(APPLICATION_THEME_KEY, DEFAULT_THEME) } } this.currentTheme.set(themeFromPref) themeFromPref @@ -86,6 +91,13 @@ object ThemeUtils { } } + /** + * @return true if system theme is dark + */ + private fun isSystemDarkTheme(resources: Resources): Boolean { + return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + } + /** * Update the application theme * @@ -93,11 +105,14 @@ object ThemeUtils { */ fun setApplicationTheme(context: Context, aTheme: String) { currentTheme.set(aTheme) - when (aTheme) { - THEME_DARK_VALUE -> context.setTheme(R.style.AppTheme_Dark) - THEME_BLACK_VALUE -> context.setTheme(R.style.AppTheme_Black) - else -> context.setTheme(R.style.AppTheme_Light) - } + context.setTheme( + when (aTheme) { + SYSTEM_THEME_VALUE -> if (isSystemDarkTheme(context.resources)) R.style.AppTheme_Dark else R.style.AppTheme_Light + THEME_DARK_VALUE -> R.style.AppTheme_Dark + THEME_BLACK_VALUE -> R.style.AppTheme_Black + else -> R.style.AppTheme_Light + } + ) // Clear the cache mColorByAttr.clear() @@ -110,6 +125,7 @@ object ThemeUtils { */ fun setActivityTheme(activity: Activity, otherThemes: ActivityOtherThemes) { when (getApplicationTheme(activity)) { + SYSTEM_THEME_VALUE -> if (isSystemDarkTheme(activity.resources)) activity.setTheme(otherThemes.dark) THEME_DARK_VALUE -> activity.setTheme(otherThemes.dark) THEME_BLACK_VALUE -> activity.setTheme(otherThemes.black) } @@ -117,40 +133,6 @@ object ThemeUtils { mColorByAttr.clear() } - /** - * Set the TabLayout colors. - * It seems that there is no proper way to manage it with the manifest file. - * - * @param activity the activity - * @param layout the layout - */ - /* - fun setTabLayoutTheme(activity: Activity, layout: TabLayout) { - if (activity is VectorGroupDetailsActivity) { - val textColor: Int - val underlineColor: Int - val backgroundColor: Int - - if (TextUtils.equals(getApplicationTheme(activity), THEME_LIGHT_VALUE)) { - textColor = ContextCompat.getColor(activity, android.R.color.white) - underlineColor = textColor - backgroundColor = ContextCompat.getColor(activity, R.color.tab_groups) - } else if (TextUtils.equals(getApplicationTheme(activity), THEME_STATUS_VALUE)) { - textColor = ContextCompat.getColor(activity, android.R.color.white) - underlineColor = textColor - backgroundColor = getColor(activity, R.attr.colorPrimary) - } else { - textColor = ContextCompat.getColor(activity, R.color.tab_groups) - underlineColor = textColor - backgroundColor = getColor(activity, R.attr.colorPrimary) - } - - layout.setTabTextColors(textColor, textColor) - layout.setSelectedTabIndicatorColor(underlineColor) - layout.setBackgroundColor(backgroundColor) - } - } */ - /** * Translates color attributes to colors * diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt index 45b6f0ee65..4caa75b39c 100644 --- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider @@ -66,7 +67,7 @@ class UserCodeSharedViewModel @AssistedInject constructor( } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: UserCodeState): UserCodeSharedViewModel } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index f8eabbaed0..9766d640c7 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -21,8 +21,9 @@ import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.toggle import im.vector.app.core.platform.VectorViewModel @@ -51,7 +52,7 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User private var currentUserSearchDisposable: Disposable? = null - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: UserListViewState): UserListViewModel } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt index 3906ea687c..13d49eb20b 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt @@ -17,8 +17,9 @@ package im.vector.app.features.widgets import android.text.TextUtils -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.resources.StringProvider import kotlinx.coroutines.GlobalScope @@ -45,7 +46,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo private val stringProvider: StringProvider, private val session: Session) : WidgetPostAPIMediator.Handler { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(roomId: String): WidgetPostAPIHandler } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetViewModel.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetViewModel.kt index 1bc10e26d4..203b58f68f 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetViewModel.kt @@ -25,8 +25,9 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.widgets.permissions.WidgetPermissionsHelper @@ -55,7 +56,7 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi WidgetPostAPIHandler.NavigationCallback, IntegrationManagerService.Listener { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: WidgetViewState): WidgetViewModel } diff --git a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt index eb588ec9ae..3accc56680 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt @@ -20,8 +20,9 @@ import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.R import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch @@ -141,7 +142,7 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in } } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: RoomWidgetPermissionViewState): RoomWidgetPermissionViewModel } diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt index 48f83b6c54..a73facc009 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt @@ -24,8 +24,9 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel @@ -69,7 +70,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS private val session: Session) : VectorViewModel(initialState), KeysBackupStateListener { - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: ServerBackupStatusViewState): ServerBackupStatusViewModel } @@ -157,8 +158,8 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS } override fun onCleared() { - super.onCleared() session.cryptoService().keysBackupService().removeListener(this) + super.onCleared() } override fun onStateChange(newState: KeysBackupState) { diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt index 00df261095..61bef29d54 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt @@ -20,19 +20,19 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.widget.LinearLayout +import android.widget.FrameLayout import androidx.core.content.withStyledAttributes import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide -import im.vector.app.databinding.ItemSignoutActionBinding +import im.vector.app.databinding.ViewSignOutBottomSheetActionButtonBinding import im.vector.app.features.themes.ThemeUtils class SignOutBottomSheetActionButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { +) : FrameLayout(context, attrs, defStyleAttr) { - private val views: ItemSignoutActionBinding + private val views: ViewSignOutBottomSheetActionButtonBinding var action: (() -> Unit)? = null @@ -67,8 +67,8 @@ class SignOutBottomSheetActionButton @JvmOverloads constructor( } init { - inflate(context, R.layout.item_signout_action, this) - views = ItemSignoutActionBinding.bind(this) + inflate(context, R.layout.view_sign_out_bottom_sheet_action_button, this) + views = ViewSignOutBottomSheetActionButtonBinding.bind(this) context.withStyledAttributes(attrs, R.styleable.SignOutBottomSheetActionButton) { title = getString(R.styleable.SignOutBottomSheetActionButton_actionTitle) ?: "" diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt index 48426be723..2f8d45043b 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt @@ -26,8 +26,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import dagger.assisted.AssistedFactory import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewModel @@ -63,7 +64,7 @@ class SignoutCheckViewModel @AssistedInject constructor(@Assisted initialState: data class ExportKeys(val exporter: KeysExporter, val passphrase: String, val uri: Uri) : ViewEvents() } - @AssistedInject.Factory + @AssistedFactory interface Factory { fun create(initialState: SignoutCheckViewState): SignoutCheckViewModel } @@ -107,8 +108,8 @@ class SignoutCheckViewModel @AssistedInject constructor(@Assisted initialState: } override fun onCleared() { - super.onCleared() session.cryptoService().keysBackupService().removeListener(this) + super.onCleared() } override fun onStateChange(newState: KeysBackupState) { diff --git a/vector/src/main/res/layout/item_expandable_textview.xml b/vector/src/main/res/layout/item_expandable_textview.xml index 9f61a3c4d4..4dc7085737 100644 --- a/vector/src/main/res/layout/item_expandable_textview.xml +++ b/vector/src/main/res/layout/item_expandable_textview.xml @@ -6,7 +6,7 @@ android:layout_height="wrap_content" android:padding="16dp"> - - - - - - - - \ No newline at end of file diff --git a/vector/src/main/res/layout/item_verification_action.xml b/vector/src/main/res/layout/item_verification_action.xml index ae49893792..68ee392cff 100644 --- a/vector/src/main/res/layout/item_verification_action.xml +++ b/vector/src/main/res/layout/item_verification_action.xml @@ -24,10 +24,10 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:src="@drawable/ic_share" - tools:visibility="visible" app:tint="?riotx_text_primary" - tools:ignore="MissingPrefix" /> + tools:ignore="MissingPrefix" + tools:src="@drawable/ic_share" + tools:visibility="visible" /> + tools:ignore="MissingPrefix" + tools:src="@drawable/ic_arrow_right" /> diff --git a/vector/src/main/res/layout/view_bottom_sheet_action_button.xml b/vector/src/main/res/layout/view_bottom_sheet_action_button.xml new file mode 100644 index 0000000000..c0f55df9e6 --- /dev/null +++ b/vector/src/main/res/layout/view_bottom_sheet_action_button.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/view_call_controls.xml b/vector/src/main/res/layout/view_call_controls.xml index 435520b9ef..2487f131e3 100644 --- a/vector/src/main/res/layout/view_call_controls.xml +++ b/vector/src/main/res/layout/view_call_controls.xml @@ -1,9 +1,10 @@ - + android:layout_height="wrap_content" + tools:parentTag="android.widget.FrameLayout"> + app:tint="@color/white" + tools:ignore="MissingConstraints,MissingPrefix" /> + app:tint="@color/white" + tools:ignore="MissingConstraints,MissingPrefix" /> + app:tint="?attr/riotx_text_primary" + tools:ignore="MissingConstraints,MissingPrefix" /> + tools:src="@drawable/ic_microphone_on" /> + app:tint="@color/white" + tools:ignore="MissingConstraints,MissingPrefix" /> + tools:ignore="MissingConstraints,MissingPrefix" /> + app:tint="?attr/riotx_text_primary" + tools:ignore="MissingConstraints,MissingPrefix" /> - \ No newline at end of file + \ No newline at end of file diff --git a/vector/src/main/res/layout/item_timeline_event_poll_result_item.xml b/vector/src/main/res/layout/view_poll_result_line.xml similarity index 100% rename from vector/src/main/res/layout/item_timeline_event_poll_result_item.xml rename to vector/src/main/res/layout/view_poll_result_line.xml diff --git a/vector/src/main/res/layout/view_sign_out_bottom_sheet_action_button.xml b/vector/src/main/res/layout/view_sign_out_bottom_sheet_action_button.xml new file mode 100644 index 0000000000..6809cfd119 --- /dev/null +++ b/vector/src/main/res/layout/view_sign_out_bottom_sheet_action_button.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index bcb33267a5..e05375b68b 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -475,7 +475,7 @@ Wer kann den Chatverlauf lesen? Wer kann auf diesen Raum zugreifen? - Jeder + Jede*r Nur Mitglieder (ab dem Zeitpunkt, an dem diese Option ausgewählt wurde) Nur Mitglieder (ab dem Zeitpunkt, an dem sie eingeladen wurden) Nur Mitglieder (ab dem Zeitpunkt, an dem sie beigetreten sind) @@ -1211,7 +1211,7 @@ Willkommen zu Hause! Unterhaltungen Räume - Deine Räume werden hier angezeigt + Deine Räume werden hier angezeigt. Drück auf das + unten rechts, um bestehende zu durchstöbern oder neue zu eröffnen. Reaktionen Zustimmen Mag ich @@ -1255,7 +1255,7 @@ Schlüssel-Ungleichheit Benutzer-Ungleichheit Informiere dich hier über ungelesene Nachrichten - Deine direkten Konversationen werden hier angezeigt + Deine direkten Konversationen werden hier angezeigt. Drück auf das + unten rechts, um eine zu beginnen. Fehlerhaftes Ereignis, kann nicht angezeigt werden Beim Abrufen der Vertrauensinformationen ist ein Fehler aufgetreten Beim Abrufen der Schlüsselsicherungsdaten ist ein Fehler aufgetreten @@ -1705,7 +1705,7 @@ Sendet das angegebene Emote in Regenbogenfarben Zeitleiste Nachrichteneditor - Aktivieren Ende-zu-Ende-Verschlüsselung + Ende-zu-Ende-Verschlüsselung aktivieren… Einmal aktiviert kann die Verschlüsselung nicht rückgängig gemacht werden. Verschlüsselung aktivieren\? Nach der Aktivierung kann die Verschlüsselung für einen Raum nicht deaktiviert werden. In einem verschlüsselten Raum gesendete Nachrichten können vom Server nicht gesehen werden, nur von den Teilnehmenden des Raums. Durch die Verschlüsselung funktionieren viele Bots und Bridges möglicherweise nicht ordnungsgemäß. @@ -2121,7 +2121,7 @@ Bestätige PIN um die PIN zu deaktivieren Verhindere versehentliche Anrufe Bitte um Bestätigung, bevor du einen Anruf tätigst - Konfiguration + Einrichten Dir fehlt die Berechtigung in diesem Raum eine Konferenz zu starten Es ist bereits eine Konferenz aktiv! Starte eine Videokonferenz @@ -2265,4 +2265,75 @@ Nach Name oder ID suchen Gib die Erlaubnis, um auf die Kamera zu zugreifen. Um den QR-Code zu scannen, muss der Zugriff auf die Kamera erlaubt werden. + Öffentliche Adressen + Raumadressen + Raumadressen und Sichtbarkeit im Raumverzeichnis ansehen und bearbeiten. + Raumadresse + Raumzugang + Änderungen daran, wer die Chronik lesen kann, gellten nur für kommende Nachrichten in diesem Raum. Die Sichtbarkeit der bestehenden Chronik bleibt unverändert. + Zurückziehen + Hinzufügen + Mit Nachricht teilen + Erweiterte Optionen ausblenden + Erweiterte Optionen anzeigen + Die Sichtbarkeit des Raums konnte nicht abgerufen werden (%1$s). + Matrix-Link + QR-Code nicht gescannt! + Inkorrekter QR code (invalide URL)! + Du kannst dir selbst keine Direktnachricht schicken! + Ändere deine aktuelle PIN + PIN ändern + Suche nach Kontakten auf Matrix + Avatar einrichten + Einverständnis wurde nicht abgegeben. + Teile diesen Code mit Leuten, damit sie ihn scannen und mit dir chatten können. + Meinen Code teilen + Mein Code + Scanne einen QR code + Das ist kein korrekter QR-Code von Matrix + 🔐️ Komm mit zu Element + Hey, schreibe mit mir auf Element: %s + Freunde einladen + Leute hinzufügen + "Thema " + Füge ein Thema hinzu + %s, um zu zeigen um was es in diesem Raum geht. + Das ist der Anfang deiner Direktnachrichten mit %s. + Das ist der Anfang dieser Konversation. + Das ist der Anfang von %s. + Du hast nicht die nötigen Berechtigungen, um die Verschlüsselung in diesem Raum zu aktivieren. + Erstelle Raum… + Manche Zeichen sind nicht zulässig + Bitte gib eine Raumadresse an + Diese Adresse ist bereits vergeben + Raumadresse + Aktivieren, wenn der Raum nur von Mitgliedern deines Homeservers zur internen Kommunikation verwendet wird. Das kann später nicht mehr geändert werden. + Begrenze Zugang zu diesem Raum (für immer!) auf Mitglieder von %s + %1$d von %2$d + QR-Code scannen, um eine neue Direktnachtricht schicken + Um bestehende Kontakte zu finden, ist es notwendig, Ihre Kontaktdaten (Telefonnummern und/oder E-Mails) mit dem ausgewählten Identitätsserver (%1$s) zu teilen. +\n +\nFür mehr Datenschutz werden die gesendeten Daten vor dem Versenden gehasht. + Keine Vorschau für diesen Raum verfügbar. Willst du direkt beitreten\? + Der Raum ist gerade nicht zugänglich. +\nVersuche es später nochmal, oder bitte einen Raum-Admin um Hilfe. + Eine neue Adresse veröffentlichen + Mit einer öffentlichen Adresse kann jede*r mit jedem Server deinem Raum beitreten. Um eine Adresse zu veröffentlichen, muss sie zuerst als lokale Adresse gesetzt sein. + Diesen Raum im Verzeichnis von %1$s veröffentlichen\? + Die Adresse \"%1$s\" nicht mehr veröffentlichen\? + Diese Adresse nicht mehr veröffentlichen + Diese Adresse veröffentlichen + Lokale Adresse hinzufügen + Dieser Raum hat keine lokalen Adressen + Füge Adressen für diesen Raum hinzu, damit andere Nutzer ihn auf %1$s finden können + Lokale Adresse + Neue öffentliche Adresse (z.B. #alias:server) + Noch keine weiteren öffentlichen Adressen vorhanden. + Noch keine weiteren öffentlichen Adressen vorhanden, füge unten eine hinzu. + Diesen Raum im Verzeichnis von %1$s veröffentlichen\? + Die Adresse \"%1$s\" löschen\? + Veröffentlichen + Andere öffentliche Adressen: + Hauptadresse + Das ist die Hauptadresse \ No newline at end of file diff --git a/vector/src/main/res/values-el/strings.xml b/vector/src/main/res/values-el/strings.xml index 5b3f3aaafc..5eb8750c15 100644 --- a/vector/src/main/res/values-el/strings.xml +++ b/vector/src/main/res/values-el/strings.xml @@ -32,7 +32,7 @@ Εντάξει Προειδοποίηση Συνέχεια - Γίνεται συγχρονισμός + Γίνεται συγχρονισμός… Ηχητικές ειδοποιήσεις Αθόρυβες ειδοποιήσεις Μηνύματα @@ -96,7 +96,7 @@ Δεν υπάρχουν δωμάτια Δεν υπάρχουν δημόσια δωμάτια - 1 χρήστης + %d χρήστης %d χρήστες Πρόσκληση @@ -333,4 +333,222 @@ Κανένα Παραμείνατε H δημιουργία αντιγράφων κλειδιού ασφαλείας θα πρέπει να είναι ενεργή σε όλες τις συνεδρίες σας για να αποφύγετε την απώλεια πρόσβασης στα κρυπτογραφημένα μηνύματά σας. + Επαναφόρτωση γραφικού στοιχείου + Αποτυχία φόρτωσης γραφικού στοιχείου +\n%s + Η χρήση του ενδέχεται να δημιουγίσει cookies και να κοινοποιήσει δεδομένα με %s: + Η χρήση του ενδέχεται να κοινοποιεί δεδομένα με %s: + Αυτο το γραφικό στοιχείο προστέθηκε από: + Φόρτωση Γραφικού στοιχείου + Γραφικό στοιχείο + Ενεργά γραφικά στοιχεία + Προβολή + Είστε βέβαιοι ότι θέλετε να διαγράψετε το γραφικό στοιχείο από αυτό το δωμάτιο; + Δημιουργήστε κλήσεις συνδιάσκεψης με το jitsi + Η δημιουργία γραφικού στοιχείου απέτυχε + Χρειάζεστε άδεια για να τροποποιήσετε τα γραφικά στοιχεία (widgets) σε αυτό το δωμάτιο + Εξαιρετικά Μεγάλο + Μεγαλύτερο + Αναζήτηση ιστορικού + %1$s: %2$s %3$s + %1$s: %2$s + ** Αποτυχία αποστολής - Παρακαλώ ανοίξτε το δωμάτιο + Εγώ + Καυνούργια Πρόσκληση + Καινούργια Μηνύματα + Δωμάτιο + Καινούργιο Συμβάν + %1$s και %2$s + %1$s στο %2$s και %3$s + + %d ειδοποιήση + %d ειδοποιήσεις + + + %1$s: %2$d μήνυμα + %1$s: %2$d μηνύματα + + + %d πρόσκληση + %d προσκλήσεις + + + 1 μη αναγνωσμένη ειδοποίηση + %d μη αναγνωσμένες ειδοποιήσεις + + Σύνδεση + Λόγος οριστικής αποβολής + Οριστική αποβολή χρήστη + Αποβάλλοντας αυτό το χρήση θα τους αφαιρέσαι από το δωμάτιο. +\n +\nΕάν θέλετε να τους αποτρέψετε να συμμετάσχουν ξανά, θα πρέπει να τους αποβάλλετε οριστικά. + Λόγος αποβολής + Αποβολή χρήστη + Είστε σίγουροι πως θέλετε να καταργήσετε την πρόσκληση προς αυτό τον χρήστη; + Ακύρωση πρόσκλησης + Κατάργηση παράβλεψης + Καταργώντας την παράβλεψη αυτού του χρήστη θα επανφανίσει όλα τα μηνύματα από αυτούς. + Παράβλεψη χρήστη + Παραβλέποντας αυτό το χρήση θα αφαιρέσει τα μηνύματα τους από δωμάτια που μοιράζεστε. +\n +\nΜπορείτε να αντιστρέψετε αυτή την ενέργεια οποτεδήποτε στις γενικές ρυθμίσεις. + Παράβλεψη + Κατάργηση παράβλεψης χρήστη + Υποβίβαση + Αυτή δεν είναι έγκυρη διεύθυνση διακομιστή Matrix + Aυτή η διεύθυνση δεν είναι προσβάσιμη, παρακαλώ ελέγξτε + Παρακαλω εισάξετε έγκυρη διεύθυνση + Όνομα χρήστη + Νέος κωδικός + Κωδικός + Ηλεκτρονική διεύθυνση ή όνομα χρήστη + Επιστροφή στην οθόνη σύνδεσης + Υποβολή + Δημιουργία Λογαριασμού + Αυτό το δωμάτιο δεν έχει τοπικές διευθύνσεις + Να μην αποστέλλονται κρυπτογραφημένα μηνύματα σε μή επαληθευμένες περιόδους σύνδεσης σε αυτό το δωμάτιο από αυτή την περίοδο σύνδεσης. + Κρυπτογράφηση μόνο επαληθευμένων περιόδους σύνδεσης + Πρέπει να αποσυνδεθείτε για να μπορέσετε να ενεργοποιήσετε την κρυπτογράφηση. + Ενεργή κρυπτογράφηση από άκρο σε άκρο + Κρυπτογράφηση από άκρο σε άκρο + Αυτά είναι πειραματικά χαρακτηριστικά τα οποία μπορούν να παρουσιάσουν μη αναμενόμενα σφάλματα. Χρησιμοποιήστε με προσοχή. + Εργαστήρια + Εσωτερικός κωδικός δωματίου + + %d απαγορευμένος χρήστης + %d απαγορευμένοι χρήστες + + Απαγορευμένοι χρήστες + Όποιος γνωρίζει τη διεύθυνση δωματίου, συμπεριλαμβανομένων των επισκεπτών + Όποιος γνωρίζει τη διέθυνση δωματίου, εκτός από επισκέπτες + Μόνο όσοι έχουν προσκληθεί + Για να δημιουργήσετε σύνδεση σε ένα δωμάτιο, πρέπει να έχει διεύθυνση. + Μέλη μόνο (από τη στιγμή που μπήκαν) + Μέλη μόνο (από τη στιγμή που καλέστηκαν) + Μέλη μόνο (από τη στιγμή επιλογής αυτής της ρύθμισης) + Δημοσίευση αυτού του δωματίου στο κοινό κατάλογο δωματίων του %1$s; + Δεν είναι δυνατή η ανάκτηση της τρέχουσας ορατότητας καταλόγου δωματίων (%1$s). + Κατάργηση δημοσίευσης αυτής της διεύθυνσης + Δεν βρέθηκαν εξωτερικές εφαρμογές για αυτή την πράξη. + συνεχίστε με… + Δεν έχετε ενεργοποιημένα πακέτα αυτοκόλλητων. +\n +\nΘέλετε να προσθέσετε μερικά τώρα; + Φωτογραφία ή βίντεο + Βίντεο + Φωτογραφία + Αποστολή αυτοκόλλητου + Ενεργοποίηση Υψηλής Ανάλυσης + Απενεργοποίηση Υψηλής Ανάλυσης + Πίσω + Μπροστινή + Αλλαγή Κάμερας + Ασύρματο Ακουστικό + Ακουστικό + Ομιλητής + Τηλέφωνο + Αλλαγή Συσκευής Ήχου + Αποτυχία σύνδεσης σε πραγματικό χρόνο. +\nΖητήστε από τον διαχειριστή του οικιακού σας διακομιστή να διαμορφώσει έναν διακομιστή TURN ώστε οι κλήσεις να λειτουργούν αξιόπιστα. + Η Κλήση Element Aπέτυχε + Να μην ερωτηθώ ξανά + Προσπαθήστε να χρησιμοποιήσετε το %s + Παρακαλώ ζητήστε απο τον διαχειριστή του ιδιέταιρου διακομιστή (%1$s) να ρυθμίσει ένα διακομιστή TURN ώστε οι κλήσεις να δουλέυουν αξιόπιστα. +\n +\nΑλλιώς, μπορείτε να δοκιμάσετε τον δημόσιο διακομιστή στο %2$s, αλλά αυτό δεν θα είναι τόσο αξιόπιστο, και η IP διέυθυνσή σας θα σταλεί σε αυτό το διακομιστή. Μπορείτε να διαχειριστείτε τη διαδικασία στις Ρυθμίσεις. + Η κλήση απέτυχε λόγω λανθασμένα ρυθμισμένου διακομιστή + Είσαστε σίγουροι ότι θέλετε να κάνετε κλήση βίντεο; + Είσαστε σίγουροι ότι θέλετε να κάνετε κλήση ήχου; + Είσαστε σίγουροι οτι θέλετε να ξεκινήσετε μια νέα συζήτηση με τον/την %s; + Αποστολή φωνής + Κλήση βίντεο + Κλήση ήχου + Νέα συζήτηση + Διέυθυνση URL Ιδιαίτερου Διακομιστή + Διεύθυνση URL Διακομιστή Ταυτότητας + Είσοδος στο δωμάτιο + Αποστολή εντός + Η εφαργμογή διακόπηκε απότομα προηγουμένως. Θα θέλατε να ανοίξετε την οθόνη αναφοράς σφάλματος; + Αποστολή στιγμιότυπου οθόνης + Αποστολή ιστορικού αιτήσεων αποστολής κλειδιού + Δεν τέθηκε διακομιστής ταυτότητας. + Δεν υπάρχουν άλλα αποτελέσματα + Βιβλίο διευθύνσεων + Επιτυχία + Κατάργηση δημοσίευσης + Αντιγραφή + Ιστορικά + Τέλος κλήσης + Τρέχουσα κλήση συνδιάσκεψης. +\nΣυνδεθείτε με %1$s ή %2$s + Δεν επιτρέψατε στο Element την πρόσβαση στις επαφές σας + Ειδοποιήσεις + Αντιγράφηκε στο πρόχειρο + Πρόσθεση + Σημείωσε ως διαβασμένο + Είσαστε σίγουροι ότι θέλετε να αποσυνδεθείτε; + Ξεκινήστε συζήτηση + Παρακαλώ εισάγετε όνομα χρήστη. + Παρακαλώ ξεχάστε όλα τα μηνύματα τα οποία έχω στείλει μόλις απενεργοποιηθεί ο λογαριασμός μου (Προειδοποίηση: αυτό σημαίνει οτι μελλοντικοί χρήστες θα έχουν μία ατελή εικόνα των συζητήσεων) + Αυτό θα κάνει το λογαριασμό σας μόνιμα άχρηστο. Δε θα μπορέσετε να συνδεθείτε ξανα, και κανείς δεν θα μπορεί να εγγραφεί με το ίδιο όνομα χρήστη. Ο λογαριασμός σας θα αναχωρήσει από όλα τα δωμάτια στα οποία συμμετέχει, και οι πληροφορίες λογαριασμού θα αφαιρεθούν από το διακομιστή ταυτότητας. Αυτή η πράξη είναι μη αναστρέψιμη. +\n +\nΜε την απενεργοποίηση του λογαρισμού σας δεν θα ξεχαστούν τα μηνύματά που έχετε στείλει. Εάν θα θέλατε να ξεχαστούν, τότε δηλώστε το στο κουτί πιο κάτω. +\n +\nΗ ορατότητα μηνυμάτων δουλεύει σαν το ηλεκτρονικό ταχυδρομείο. Το να ξεχαστούν τα μηνύματα σημαίνει οτι μηνύματα τα οποία έχετε στείλει δεν θα σταλούν σε νέους ή μη-εγγεγραμμένους χρήστες, αλλα εγγεγραμμένοι χρήστες οι οποίοι έχουν ήδη πρόσβαση σε αυτά τα μηνύματα θα μπορούν ακόμα να τα δούν. + Λησμόνηση δωματίου + Αυτό το δωμάτιο έχει αντικατασταθεί και δεν είναι πια ενεργό + Μιλήστε + Παράβλεψη + Αποσύνδεση + Δεν εμπιστεύομαι + Δεν έχετε εξουσιοδότηση να δημοσιεύσετε σε αυτό το δωμάτιο + Το αρχείο δεν βρέθηκε + Διαγραφή μηνυμάτων που δεν στάληκαν + Επαναποστολή μηνυμάτων που δεν στάληκαν + Ακύρωση όλων + Επαναποστολή όλων + Απώλεια σύνδεσης με το διακομιστή. + Αποστολή απάντησης (κρυπτογραφημένη)… + Αποστολή κρυπτογραφημένης απάντησης… + Αποστολή μηνύματος (κρυπτογραφημένο)… + Αποστολή κρυπτογραφημένου μηνύματος… + %1$s & %2$s & άλλοι γράφουν… + %s γράφει… + %1$s & %2$s γράφουν… + Συνομιλία + Διεύθυνση ηλεκτρονικού ταχυδρομίου ή Matrix ID + Πρόσκληση μέσω ID χρήστη + Μόνο χρήστες Matrix + Ευρετήριο χρηστών (%s) + Είστε σίγουροι ότι θέλετε να προσκαλέσετε τους %s σε αυτή την συζήτηση; + Λόγος + Δεν εξακριβώθηκε η ταυτότητα του εξωτερικού διακομιστή. + Απόκρυψη όλων των μηνυμάτων από αυτό το χρήστη; +\n +\nΑυτή η ενέργεια θα επανεκκινήσει την εφαρμογή και ίσως πάρει λίγο χρόνο. + Λόγοι αναφοράς αυτού του περιεχομένου + Ρυθμίσεις + Λεπτομέρειες Δωματίου + ΚΑΛΕΣΜΕΝΟΣ/Η + Πληκτρολογείστε ταυτότητα (ID) δωματίου ή ψευδώνυμο δωματίου + Ένταξη στο δωμάτιο + Δημιουργία δωματίου + ΠΡΟΣΚΛΗΣΕΙΣ + ΧΑΜΗΛΗ ΠΡΟΤΕΡΑΙΟΤΗΤΑ + ΔΩΜΑΤΙΑ + ΣΥΜΜΕΤΟΧΗ + Η αναζήτηση σε κρυπτογραφημένα δωμάτια δεν υποστηρίζεται ακόμα. + ΑΡΧΕΙΑ + ΜΗΝΥΜΑΤΑ + ΔΩΜΑΤΙΑ + Κανένα αποτέλεσμα + Φιλτράρισμα αποβεβλημένων χρηστών + Φιλτράρισμα μελών δωματίου + Εύρεση + Ακύρωση Λήψης + Ακύρωση Αποστολής + Παραποιημένη ταυτότητα (ID). Πρέπει να είναι διεύθυνση ηλ. ταχυδρομίου ή ταυτότητα (ID) τύπου Matrix, όπως @localpart:domain\' + Αποδεκτείτε το πιστοποιητικό εαν ο διαχειριστής του διακομιστή έχει εκδόσει ένα αποτύπωμα που ταιριάζει με το παρά πάνω. + Το πιστοποιτικό έχει αλλάξει από ένα προηγούμενο αξιόπιστο, σε ένα αναξιόπιστο. Ο διακομιστής ενδέχεται να έχει αλλάξει το πιστοποιητικό του. Επικοινωνείστε με το διαχειριστή του διακομιστή για το αναμενόμενο αποτύπωμα. + Το πιστοποιητικό έχει αλλάξει από αυτό που εμπιστεύθηκε προηγουμένως η συσκευή σας. Αυτό είναι ΑΚΡΩΣ ΑΣΥΝΗΘΙΣΤΟ. Προτείνεται να ΜΗΝ ΑΠΟΔΕΚΤΕΙΤΕ το νεο πιστοποιητικό. \ No newline at end of file diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index 6bc5b3cd8c..d688f81c35 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -45,7 +45,7 @@ Saada uuesti Eemalda Tsiteeri - Lae alla + Laadi alla Jaga Räägi Eemalda @@ -334,7 +334,7 @@ \nKõnede tegemiseks palun anna järgmisel lehel vajalikud õigused. Vabandust. Kuna vastavaid õigusi ei olnud, siis toimingut ei saanud teha Salvestatud - Kas salvestame allalaetud failide kausta\? + Kas salvestame allalaaditud failide kausta\? JAH EI Jätka @@ -526,7 +526,7 @@ %s soovib verifitseerida sinu sessiooni Kasutaja tühistas verifitseerimise Verifitseerimisprotsess aegus - Sinu jututoad kuvatakse siin + Sinu jututoad kuvatakse siin. Olemasolevate jututubade leidmiseks või uute tegemiseks klõpsi all paremal nurgas asuvat + nuppu. Reageerimised Nõus Meeldib @@ -1413,7 +1413,7 @@ Võrguühenduse viga: palun kontrolli, kas võrguühendus on olemas ja proovi uuesti. Taastan võtmed varundusest: Arvutan taastevõtit… - Laen alla krüptovõtmeid… + Laadin alla krüptovõtmeid… Impordin krüptovõtmeid… Selle taastevõtmega ei õnnestunud varundust dekrüptida: palun kontrolli, kas sa kasutad õiget taastevõtit. Varukoopiast taastatud %s! @@ -1503,7 +1503,7 @@ Tere tulemast koju! Leiad lugemata sõnumid siit Vestlused - Sinu otsevestlused kuvatakse siin + Sinu otsevestlused kuvatakse siin. Vestluse alustamiseks klõpsi all paremal nurgas asuvat + nuppu. Jututoad Usaldamiseks vajaliku teabe laadimisel tekkis viga Krüptovõtmete varukoopia andmete laadimisel tekkis viga @@ -1535,8 +1535,8 @@ Saadan pisipilti (%1$s / %2$s) Krüptin faili… Saadan faili (%1$s / %2$s) - Laen alla faili %1$s… - %1$s on alla laetud! + Laadin alla faili %1$s… + %1$s on alla laaditud! (muudetud) Sõnumite muutmised Muutmisi ei leidunud @@ -1713,7 +1713,7 @@ Meil ei õnnestunud neile kasutajatele kutset saata. Palun kontrolli, keda soovid kutsuda ning proovi uuesti. Hetkel kasutatav keel Muud saadaval olevad keeled - Laen saadaval olevaid keeli… + Laadin saadaval olevaid keeli… Ava %s kasutustingimused Kas katkestame ühenduse isikutuvastusserveriga %s\? Palun esmalt seadista isikutuvastusserver. @@ -1952,7 +1952,7 @@ Üks inimene %1$d inimest - Üleslaetud failid + Üleslaaditud failid Lahku jututoast Lahkun jututoast… Haldajad @@ -2246,4 +2246,37 @@ Anna õigused oma kontakte lugeda. QR-koodi lugemiseks pead selleks kaamerale õigused andma. Alusta vestlust + Muuda oma praegune PIN-kood + Muuda PIN-kood + Antud jututoal puudub eelvaate võimalus. Kas sa soovid sellega liituda\? + Sellele jututoale puudub hetkel ligipääs. +\nProovi hiljem uuesti või küsi jututoa haldajalt, kas sul on olemas selleks vajalikud õigused. + Ei õnnestu laadida andmeid selle jututoa nähtavuse kohta (%1$s). + Kas avaldame selle jututoa %1$s serveri kõigile nähtavad jututubade loendis\? + Tühista selle aadressi avaldamine + Avalda see aadress + Lisa kohalik aadress + Sellel jututoal puuduvad kohalikud aadressid + Et muud kasutajad saaks seda jututuba leida sinu koduserveri (%1$s) kaudu, lisa sellele jututoale aadresse + Kohalikud aadressid + Uus avaldatud aadess (näiteks #alias:server) + Ühtegi muud aadressi pole veel avaldatud. + Ühtegi muud aadressi pole veel avaldatud, lisa üks alljärgnevalt. + Kas avaldame selle jututoa %1$s serveri jututubade loendis\? + Kas kustutame „%1$s“ aadressi\? + Kas lõpetame „%1$s“ aadressi avaldamise\? + Avalda + Avalda uus aadress käsitsi + Muud avaldatud aadressid: + Põhiaadress + See on põhiaadress + Avaldatud aadresse saab mis iganes serveri kasutaja pruukida sinu jututoaga liitumiseks. Aadressi avaldamiseks peab ta alustuseks olema määratud kohaliku aadressina. + Avaldatud aadressid + Jututoa aadressid + Vaata ja halda selle jututoa aadresse ning nähtavust lututubade loendis. + Jututoa aadressid + Ligipääs jututuppa + Kui muudad seda, kes saavad selle jututoa ajalugu lugeda, siis kehtib see vaid tulevaste sõnumite kohta. Senise ajaloo nähtavus sellega ei muutu. + Tühista avaldamine + Lisa \ No newline at end of file diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index 0663dd1dca..daa8f460c9 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -241,7 +241,7 @@ ماندن حذف بارگیری - کنفرانس در حال برگزاری است. + کنفرانس در حال برگذاری است. \nبه صورت %1$s یا %2$s به آن بپیوندید به خاطر نداشتن مجوز دسترسی، برخی امکانات ممکن است در دسترس نباشند… به خاطر نداشتن مجوز دسترسی، این اقدام ممکن نیست. @@ -250,7 +250,7 @@ رد شدن انجام شد انصراف - چشم‌پوشی + نادیده‌گرفتن آیا می‌خواهید از حساب کاربری خود خارج شوید؟ علامت‌گذاری به عنوان خوانده شده ورود با سامانه‌های احراز هویت مرکزی @@ -366,7 +366,7 @@ پاک‌سازی انبارهٔ رسانه تنظیمات کاربر آگاهی‌ها - کاربران چشم‌پوشیده + کاربران نادیده‌گرفته شده دیگر پیش‌رفته یک‌پارچگی‌ها @@ -456,9 +456,9 @@ به خانه خوش آمدید! این‌جا به پیام‌های نخوانده برسید گفت‌وگوها - گفت‌گوهای پیام مستقیمتان این‌جا نشان داده خواهند شد + گفت‌گوهای پیام مستقیمتان این‌جا نشان داده خواهند شد. برای آغاز روی + در پایین سمت راست بزنید. اتاق‌ها - اتاق‌هایتان این‌جا نشان داده خواهند شد + اتاق‌هایتان این‌جا نشان داده خواهند شد. برای یافتن موارد موجود یا ایجاد خودتان روی + در پایین سمت راست بزنید. بازخودها موافقت پسند @@ -492,8 +492,8 @@ امنیت و محرمانگی صدا و تصویر راهنما و درباره - ارایهٔ پیشنهاد - لطفاً پیشنهادتان را در زیر بنویسید. + پیشنهاد دهید + لطفا پیشنهادتان را در زیر بنویسید. پیشنهادتان را این‌جا شرح دهید ممنون. پیشنهاد با موفّقیت فرستاده شد فرستادن پیشنهاد شکست خورد (%s) @@ -523,13 +523,13 @@ گزارش این محتوا دلیل گزارش این محتوا گزارش - چشم‌پوشی از کاربر + نادیده‌گرفتن کاربر محتوا گزارش شد به عنوان هرزنامه گزارش شد به عنوان نامناسب گزارش شد - چشم‌پوشی از کاربر + نادیده‌گرفتن کاربر تنظیمات پیش‌رفته و سفارشی - دیدن تمام نشست‌هایم + دیدن همه نشست‌هایم تنظیمات پیش‌رفته حالت توسعه‌دهنده تکان دادن @@ -541,7 +541,7 @@ خط زمانی ویرایشگر پیام نشست‌های فعّال - نمایش تمامی نشست‌ها + نمایش همه نشست‌ها مدیریت نشست‌ها ۱ نشست فعّال @@ -604,8 +604,8 @@ بازنشانی به کاربر عادی ناظر کردن مدیر کردن - چشم‌پوشی - نمایش همه پیام‌ها از این کاربر + نادیده‌گرفتن + لغو نادیده‌گیری اشاره نمایش فهرست نشست انسداد کاربر، او را از این اتاق اخراج کرده و از پیوستن دوباره‌اش جلوگیری می‌کند. @@ -677,8 +677,8 @@ این پیش‌نمایی از اتاق است. برهم‌کنش‌های اتاق از کار افتاده‌اند. برای انجام این عمل، کارساز هویتی را به تنظیماتتان بیفزایید. لغو دعوت - چشم‌پوشی از کاربر - نادیده نگرفتن کاربر + نادیده گرفتن کاربر + لغو نادیده‌گیری کاربر لغو دعوت مطمئنید که می‌خواهید دعوت این کاربر را لغو کنید؟ اخراج کاربر @@ -720,7 +720,7 @@ اعتماد کردن اعتماد نکردن خروج - چشم‌پوشی + نادیده‌گرفتن اثرانگشت (%s): نمی‌توان هویت کارساز دوردست را تأیید کرد. جست‌وجو @@ -773,7 +773,7 @@ از کار انداختن محدودیت‌ها بهینه‌سازی باتری المنت تحت تأثیر بهینه‌سازی باتری نیست. - چشم‌پوشی از بهینه‌سازی + نادیده‌گرفتن بهینه‌سازی عادی محرمانگی کاهش‌یافته کاره برای اجرا در پس‌زمینه نیاز به اجازه دارد @@ -814,7 +814,7 @@ برپایی روی این افزاره سپرامنیتی در برابر از دست دادن دسترسی به داده‌ها و پیام‌های رمزشده با پشتیبان گیری از کلیدها روی کارسازتان. غیرفعّال‌سازی حساب - غیرفعّال‌سازی حسابم + حسابم را غیرفعال کن کشف مدیریت تنظیمات کشفتان. محرمانگی آگاهی @@ -976,8 +976,8 @@ هم‌رسانی بدون تأیید هم‌رسانی درخواست هم‌رسانی کلید - چشم‌پوشی از درخواست - چشم‌پوشی + نادیده‌گرفتن درخواست + نادیده‌گرفتن هشدار! خاموش خموش @@ -1079,7 +1079,7 @@ %1$s تغییری ایجاد نکرد تغییری ایجاد نکردید برای یافتن واکنش، کلیدواژگان را بنویسید. - از هیچ کاربری چشم نمی‌پوشید + شما هیچ کاربری را نادیده نمی‌گیرید میزبانی حرفه‌ای برای سازمان‌ها بیش‌تر بدانید دیگر @@ -1203,7 +1203,7 @@ پیش گزیده در %1$s سفارشی (%1$d) در %2$s پرش به رسیدِ خواندن - چشم‌ناپوشی + لغو نادیده‌گرفتن پس از به کار افتادن، رمزنگاری قابل از کار انداختن نیست. به کار انداختن رمزنگاری ورود چندگانه @@ -1256,7 +1256,7 @@ تأیید برداشت آوردن دلیل - المنت اندروید + Element Android درخواست‌های کلید قفل‌گشایی از تاریخچهٔ پیام‌های رمزشده نوسازی @@ -1339,7 +1339,7 @@ رمزنگاری در این اتاق از کار افتاده است. رونوشت از نشانی اتاق رونوشت از شناسهٔ اتاق - ناتنظیم به عنوان نشانی اصلی + بازنشاندن از نشانی اصلی رمزنگاری در این اتاق به کار افتاده است. ارتباط با مدیر خدمتتان ارتباط با مدیر @@ -1449,7 +1449,7 @@ نمایش محتوا در آگاهی‌ها کد پین، تنها راه قفل‌گشایی المنت است. به کار انداختن زیست‌سنجی‌های مختص افزاره، مانند اثرانگشت‌ها و تشخیص چهره. - به کرا انداختن زیست‌سنجی‌ها + به کار انداختن زیست‌سنجی‌ها اگر می‌خواهید پینتان را بازنشانی کنید، فراموشی پین را برای خروج و بازنشانی بزنید. به کار انداختن پین پیکربندی محافظت @@ -1553,9 +1553,9 @@ فیلترکردن کاربران مسدود شده لغو دانلود لغو آپلود - آیا مطمئن هستید که تمام پیام‌های ارسالی از طرف این کاربر پنهان شود؟ + آیا می‌خواهید که همه پیام‌های ارسالی از طرف این کاربر پنهان شود؟ \n -\nاین کار برنامه را مجدداً باز می‌کند و ممکن است کمی به طول انجامد. +\nاین کنش کاره را دوباره راه‌اندازی می‌کند و ممکن است زمان ببرد. دلیل گزارش این محتوا عضو شد دعوت‌شدگان @@ -1575,10 +1575,10 @@ پیام به دلیل حضور یک دستگاه ناشناس ارسال نشد. %1$s یا %2$s؟ پیام ارسال نشد. %1$s یا %2$s؟ با لغو مسدودیت، کاربر می‌تواند مجددا به اتاق اضافه شود. - حذف کاربر از لیست سیاه سبب می‌شود مجددا تمام پیام‌های او نمایش داده شود. - افزودن کاربر به لیست سیاه سبب می‌شود پیام های او از اتاق‌هایی که به اشتراک می گذارید حذف شود. -\n -\nهر زمان که خواستید، می‌توانید در تنظیمات کاربر را از لیست سیاه حذف کنید. + لغو نادیده‌گیری کاربر سبب می‌شود دوباره همه پیام‌های او نمایش داده شود. + نادیده‌گرفتن این کاربر پیام‌هایش را از اتاق‌های مشترکتان حذف خواهد کرد. +\n +\nهرگاه که بخواهید می‌توانید این کنش را در تنظیمات کلی لغو کنید. تنزل بده شما نمی‌توانید این تغییر را بازگردانید زیرا در حال تنزل نقش خود در اتاق هستید، اگر آخرین کاربر ممتاز در اتاق باشید، امکان دستیابی مجدد به دسترسی‌های سطح بالای اتاق غیرممکن است. تنزل نقش شما در اتاق؟ @@ -1817,13 +1817,13 @@ \nلطفاً در پنجره بعدی اجازه دسترسی دهید تا بتوانید کلیدهای خود را به صورت دستی ذخیره کنید. این محتوا به عنوان محتوای نامناسب گزارش شده‌است. \n -\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید ، می توانید او را در لیست سیاه قرار دهید تا پیام‌های او را مشاهده نکنید. +\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید ، می توانید او را نادیده بگیرید تا پیام‌های او را مشاهده نکنید. این محتوا به عنوان هرز‌نامه گزارش شده‌است. \n -\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید ، می توانید او را در لیست سیاه قرار دهید تا پیام‌های او را مشاهده نکنید. +\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید ، می توانید او را نادیده بگیرید تا پیام‌های او را مشاهده نکنید. این محتوا گزارش شده‌است. \n -\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید، می توانید او را در لیست سیاه قرار دهید تا پیام‌های او را مشاهده نکنید. +\nاگر نمی‌خواهید محتوای بیشتری از این کاربر مشاهده کنید، می توانید او را نادیده بگیرید تا پیام‌های او را مشاهده نکنید. امکان به اشتراک‌گذاری این محتوا وجود ندارد چرخش و برش اضافه کردن تصویر از @@ -2246,4 +2246,37 @@ شما عدم رضایت خود را برای ارسال ایمیل و شماره تلفن به این سرور اعلام کرده‌اید در نتیجه نمی‌توانید کاربران دیگر را با استفاده از مخاطبین خود پیدا کنید. شما رضایت خود را برای ارسال ایمیل و شماره تلفن به این سرور اعلام کرده‌اید تا بتوانید کاربران دیگر را مخاطبین خود پیدا کنید. + در حال حاضر این اتاق قابل دسترسی نیست. +\nبعدا دوباره تلاش کنید، یا از مدیر اتاق بخواهید بررسی کند که آیا دسترسی دارید. + انتشار این نشانی + منتشر کردن + منتشر کردن دستی یک نشانی جدید + نشانی‌های منتشر شده دیگر: + نشانی‌های منتشر شده + لغو انتشار + افزودن نشانی محلی + این اتاق هیچ نشانی محلی ندارد + نشانی‌های محلی + نشانی \"%1$s\" حذف شود؟ + نشانی اصلی + این نشانی اصلی است + نشانی‌های اتاق + نشانی‌های اتاق + دسترسی اتاق + افزودن + پین کنونی خود را تغییر دهید + تغییر پین + اتاق قابل پیش‌نمایش نیست. آیا می‌خواهید به آن بپیوندید؟ + لغو انتشار این نشانی + نشانی جدید منتشر شده (ب.ن. #نام:کارساز) + هنوز نشانی دیگری منتشر نشده است. + هنوز نشانی دیگری منتشر نشده است، یکی را در زیر بیفزایید. + انتشار نشانی \"%1$s\" لغو شود؟ + نشانی‌های منتشرشده را می‌توان در هر کارساز برای پیوستن به اتاق شما استفاده کرد. برای انتشار نشانی، نخست باید به عنوان نشانی محلی تنظیم شود. + نشانی‌های این اتاق و قابلیت مشاهده آن را در فهرست اتاق مشاهده و مدیریت کنید. + تغییرات برای افرادی که می توانند تاریخچه را بخوانند فقط برای پیام های بعدی این اتاق اعمال می شود. پدیداری تاریخچه موجود بدون تغییر خواهد بود. + ناتوان در گرفتن نمایانی شاخهٔ اتاق کنونی (%1$s). + انتشار این اتاق برای عموم در شاخهٔ اتاق %1$s؟ + تنظیم نشانی‌ها برای این اتاق تا کاربران بتوانند از طریق کارساز خانگیتان (%1$s) بیابندش + انتشار این اتاق برای عموم در شاخهٔ اتاق %1$s؟ \ No newline at end of file diff --git a/vector/src/main/res/values-he/strings.xml b/vector/src/main/res/values-he/strings.xml new file mode 100644 index 0000000000..dbfd579ba6 --- /dev/null +++ b/vector/src/main/res/values-he/strings.xml @@ -0,0 +1,1288 @@ + + + התראות + כפתורי ניווט תחתונים + הצלחה + שגיאה + אזהרה + אישור + השבת + העתק ללוח הגזירים + הסר פרסום + הוסף + העתק + סגור + סמן כ\'נקרא\' + תגובה מהירה + היסטורי + סמן הכל כ\'נקרא\' + חיפוש כללי + שיחת וידאו + שיחה קולית + האם אתה בטוח שברצונך לצאת מחשבונך\? + יציאה מהחשבון + פעולות + יציאה + נתק + להסיר + לקבל + יְרִידָה + סקירה + להתעלם + לְהַפִּיל + בוצע + לדלג + לְקַבֵּל + לא מקוון + להזמין + לשלוח בכל מקרה + תתקשר בכל מקרה + שיחות ועידה אינן נתמכות בחדרים מוצפנים + הסרת היישומון נכשלה + הוספת היישומון נכשלה + מידע על מושב + אתה לא יכול להתקשר עם עצמך, לחכות שהמשתתפים יקבלו את ההזמנה + אינך יכול להתקשר עם עצמך + לא ניתן להתחיל להתקשר + הפגישות משתמשות במדיניות האבטחה וההרשאה של Jitsi. כל האנשים שנמצאים כעת בחדר יראו הזמנה להצטרף בזמן שהפגישה שלך מתרחשת. + התחל פגישת שמע + התחל פגישת וידאו + ועידה כבר בעיצומה! + אין לך הרשאה להתחיל שיחה + אין לך הרשאה להתחיל שיחה בחדר זה + אין לך הרשאה להתחיל שיחת ועידה + אין לך הרשאה להתחיל שיחת ועידה בחדר זה + אתה זקוק להרשאה כדי להזמין כדי להתחיל כנס בחדר זה + בגלל הרשאות חסרות, פעולה זו אינה אפשרית. + בגלל הרשאות חסרות, ייתכן שחלק מהתכונות חסרות … + לא יכול להתחיל את השיחה, נסה שוב מאוחר יותר + וידאו + קול + התחל לצ\'וטט + אתחול + השהה + לנגן + שיחה פעילה + דווח על תוכן + התנתק + לבטל + אין + שנה שם + מחק + צפה במקור המפוענח + צפה במקור הדף + קישור קבוע + העבר + מאוחר יותר + ניקוי + דבר + שתף + הורדה + צטט + הסר + שלח שוב + שלח + הישאר + עזיבה + שמירה + ביטול + אוקיי + טוען… + רישיונות צד ג \' + תאבד את הגישה להודעות המוצפנות שלך אלא אם כן תגבה את המפתחות לפני היציאה. + גבה + האם אתה בטוח\? + השתמש בגיבוי מפתח + מגבה מקשים … + אני לא רוצה את ההודעות המוצפנות שלי + גיבוי מפתח מאובטח צריך להיות פעיל בכל ההפעלות שלך כדי למנוע אובדן גישה להודעות המוצפנות שלך. + גיבוי המפתח מתבצע. אם תצא עכשיו תאבד את הגישה להודעות המוצפנות שלך. + אם תצא עכשיו, תאבד את ההודעות המוצפנות שלך + קישור למטריקס + או + פתיחה + כניסה + שחרר + גיבוי המפתחות לא הסתיים, אנא המתן … + אמת מושב + השתמש במפתח גיבוי + גיבוי מפתח + שלח מדבקה + פרטי קהילה + דיווח תקלות + הסטוריה + פרטי משתמש + הגדרות + חדר + הודעות + התראות שקטות + התראות רועשות + האזנה לאירועים + מסנכרן… + אתחול השירות + ערכת נושא Status.im + ערכת נושא שחורה + ערכת נושא כהה + ערכת נושא בהירה + Hebr + IL + iw + + משתמש %d + %d משתמשים + מעט + אחר + + אין חדרים ציבורים + אין חדרים + רשימת חדרים + חדרים + אין שיחות + אנשי קשר מטריקס בלבד + תיקיית האב של המשתמש + פנקס כתובות מקומי + שיחות + התראות מערכת + בעדיפות נמוכה + הזמנות + סנן שמות מבין רשימת הקהילות + סנן מבין רשימת החדרים + סנן מבין רשימת האנשים + סנן מהמועדפים + סנן שמות חדרים + קהילות + חדרים + לא הוגדר שרת זהות. + אין תוצאות נוספות + אין תוצאות + לא אפשרת לאלמנט לגשת לאנשי הקשר המקומיים שלך + האם אתה בטוח שברצונך להתחיל צ\'אט חדש עם %s\? + שלח קול + התחל שיחת וידאו + התחל שיחה קולית + התחל צ\'אט חדש + חיפוש + קישור לשרת הזיהוי + קישור לשרת הבית + יציאה + כניסה + צור חשבון + שם משתמש + הצטרף אל חדר + קרא + שלח פנימה + לא ניתן היה לשלוח את דוח הבאג (%s) + דוח הבאג נשלח בהצלחה + טלטול זעם כדי לדווח על באג + היישום התרסק בפעם האחרונה. האם ברצונך לפתוח את מסך דוח הקריסה\? + נראה שאתה מטלטל את הטלפון בתסכול. האם ברצונך לפתוח את מסך דוח הבאג\? + על מנת לאבחן בעיות, יומני הלקוח יישלחו עם דוח הבאג הזה. דוח באגים זה, כולל היומנים וצילום המסך, לא יהיה גלוי לציבור. אם אתה מעדיף לשלוח רק את הטקסט למעלה, בטל את הסימון: + תאר את הבעיה שלך כאן + אם אפשר, אנא כתוב את התיאור באנגלית. + אנא תאר את הבאג. מה עשית\? מה ציפית שיקרה\? מה באמת קרה\? + דווח על באג + שלח צילום מסך + שלח היסטוריית בקשות לשיתוף מפתח + שלח יומני תקלות + שלח יומנים + אין קבוצות + קהילות + הזמנה + שם משתמש זה כבר בשימוש + יותר מדי בקשות נשלחו + לא מכיל JSON חוקי + JSON פגום + אסימון הגישה שצוין לא זוהה + שם משתמש / סיסמא שגויים + המכשיר שלך משתמש בפרוטוקול אבטחה TLS מיושן, הפגיע להתקפה, למען ביטחונך לא תוכל להתחבר + שגיאת SSL. + שגיאת SSL: זהות העמית לא אומתה. + לא ניתן להגיע לשרת בית בכתובת אתר זו, אנא בדוק זאת + זו אינה כתובת שרת מטריקס חוקית + לא ניתן להגיע לכתובת אתר זו, אנא בדוק אותה + אנא הכנס כתובת תקינה + לא ניתן להירשם: כשל בבעלות על דוא\"ל + לא ניתן להירשם + לא ניתן להירשם: שגיאת רשת + לא מצליח להתחבר + לא ניתן להתחבר: שגיאת רשת + כתובת האתר חייבת להתחיל ב- http [s]: // + אנא עיין וקבל את המדיניות של שרת בית זה: + הסיסמה שלך אופסה. +\n +\nהוצאת מכל ההפעלות ולא תקבל עוד התראות דחיפה. כדי להפעיל מחדש התראות, התחבר מחדש בכל מכשיר. + אימות כתובת הדוא\"ל נכשל: ודא שלחצת על הקישור בדוא\"ל + דוא\"ל נשלח אל%s. לאחר שתעקוב אחר הקישור שהוא מכיל, לחץ למטה. + יש להזין סיסמה חדשה. + יש להזין את כתובת הדוא\"ל המקושרת לחשבונך. + כדי לאפס את הסיסמה שלך, הזן את כתובת הדוא\"ל המקושרת לחשבונך: + אימתתי את כתובת הדוא\"ל שלי + שרת זיהוי: + שרת הבית: + שם משתמש כבר נמצא בשימוש + שרת בית זה רוצה לוודא שאתה לא רובוט + הרשמה באמצעות דוא\"ל ומספר טלפון בבת אחת עדיין אינה נתמכת עד להתקנת ה- API. רק מספר הטלפון ייקח בחשבון. +\n +\nתוכל להוסיף את הדוא\"ל שלך לפרופיל שלך בהגדרות. + אנא בדוק את הדוא\"ל שלך כדי להמשיך בהרשמה + השתמש באפשרויות שרת מותאמות אישית (מתקדם) + שכחת סיסמה\? + סיסמא אינה תואמת לקודמתה + מטבע אינו חוקי + כתובת דוא\"ל או מספר טלפון חסרים + מספר טלפון חסר + כתובת דוא\"ל חסרה + מספר הטלפון הזה כבר קיים ומעודכן במערכת. + כתובת הדוא\"ל הזו כבר קיימת ומוגדרת במערכת. + זה אינו נראה כמספר טלפון חוקי + זה לא נראה כמו כתובת דוא\"ל חוקית + סיסמה חסרה + סיסמה קצרה מדי (נדרש לפחות 6 תווים) + שמות משתמשים עשויים להכיל רק אותיות, מספרים, נקודות, מקפים וקו תחתון + שם משתמש ו/או סיסמה לא נכונים + אשר את סיסמתך החדשה + חזור על הסיסמה + מספר טלפון (אופציונלי) + מספר טלפון + כתובת דוא\"ל (אופציונלי) + כתובת דוא\"ל + הגדר דוא\"ל לשחזור חשבון. השתמש באימייל או בטלפון מאוחרים יותר כדי שאפשר יהיה לגלות אותו על ידי אנשים שמכירים אותך. + הגדר דוא\"ל לשחזור חשבון. השתמש באימייל או בטלפון מאוחרים יותר כדי שאפשר יהיה לגלות אותו על ידי אנשים שמכירים אותך. + הגדר טלפון, ואחר כך יהיה ניתן לגלות אותו על ידי אנשים שמכירים אותך. + הגדר דוא\"ל לשחזור חשבון, ומאוחר יותר כך שניתן יהיה לגלות אותו על ידי אנשים שמכירים אותך. + שם משתמש + סיסמה חדשה + סיסמה + מייל או שם משתמש + חזור למסך כניסה + שלח מייל איפוס + דלג + הגש + צור חשבון + היכנס באמצעות כניסה יחידה + היכנס + מצטערים, לא נמצאה יישום חיצוני להשלמת פעולה זו. + המשך עם… + כרגע אין לך חבילות מדבקה מופעלות. +\n +\nלהוסיף כמה עכשיו\? + צלם סרטון + צלם תמונה + צלם תמונה או סרטון + שלח סטיקר + שלח קבצים + הפעל מצב HD + כבה מצב HD + אחורה + קדימה + החלף בין מצלמה + אוזניות אלחוטיות + אוזניות + רמקול + טלפון + בחר מכשיר סאונד + נכשל החיבור בזמן אמת. +\nאנא בקש ממנהל שרת הבית שלך להגדיר שרת TURN על מנת שהשיחות יעבדו בצורה אמינה. + שיחת האלמנט נכשלה + אל תשאל אותי שוב + נסה להשתמש ב-%s + השיחה נכשלה עקב שרת שהוגדר כהלכה + האם אתה בטוח שברצונך להתחיל שיחת וידאו\? + האם אתה בטוח שברצונך להתחיל שיחה קולית\? + צ\'ט חדש + הוסף שרת זהות בהגדרות שלך כדי לבצע פעולה זו. + זו תצוגה מקדימה של החדר הזה. אינטראקציות בחדר הושבתו. + חדר + אתה מנסה לגשת ל-%s. האם תרצה להצטרף על מנת להשתתף בדיון\? + הזמנה זו נשלחה אל%s, שאינה משויכת לחשבון זה. +\nייתכן שתרצה להתחבר עם חשבון אחר, או להוסיף דוא\"ל זה לחשבונך. + הוזמנת להצטרף לחדר זה על ידי%s + קפיצה להודעה הראשונה שלא נקראה. + מסנכרן… + פתח כותרת + חברי רשימה + דחייה + תצוגה מקדימה + הצטרף + הסר + המשך + לא!! + כן! + שמור להורדות\? + נשמר + אפשר הרשאה לגשת לאנשי הקשר שלך. + כדי לסרוק קוד QR, עליך לאפשר גישה למצלמה. + מצטער. הפעולה לא בוצעה בגלל הרשאות חסרות + אלמנט יכול לבדוק את פנקס הכתובות שלך כדי למצוא משתמשי מטריקס אחרים על סמך מספרי הדוא\"ל והטלפון שלהם. +\n +\nהאם אתה מסכים לשתף את פנקס הכתובות שלך למטרה זו\? + אלמנט יכול לבדוק את פנקס הכתובות שלך כדי למצוא משתמשי מטריקס אחרים על סמך מספרי הדוא\"ל והטלפון שלהם. אם אתה מסכים לשתף את פנקס הכתובות שלך למטרה זו, אנא הגש גישה בחלון הקופץ הבא. + אלמנט זקוק להרשאה כדי לגשת למצלמה ולמיקרופון שלך כדי לבצע שיחות וידאו. +\n +\nאנא אפשר גישה בחלונות הקופצים הבאים כדי להיות מסוגל לבצע את השיחה. + " +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לבצע את השיחה." + אלמנט זקוק להרשאה כדי לגשת למיקרופון שלך כדי לבצע שיחות שמע. + " +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לבצע את השיחה." + אלמנט זקוק להרשאה כדי לגשת למצלמה שלך כדי לצלם תמונות ושיחות וידאו. + אלמנט זקוק להרשאה כדי לגשת לספריית התמונות והווידיאו שלך כדי לשלוח ולשמור קבצים מצורפים. +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לשלוח קבצים מהטלפון שלך. + מידע + לא ניתן להקליט וידאו + צלם תמונה או סרטון + השיחה נענתה במקום אחר + לא ניתן לאתחל את המצלמה + חיבור המדיה נכשל + הצד המרוחק לא הצליח להרים. + חזור לשיחה + שיחה פעילה (%s) + שיחת וידאו מתבצעת … + במהלך התקשרות… + שיחה קולית נכנסת + שיחת וידאו נכנסת + שיחה נכנסת + מתקשר… + שיחה הסתיימה + שיחה מתחברת … + שיחה מחוברת + שִׂיחָה + בחר רינגטון לשיחות: + רינגטון שיחה נכנסת + ישתמש ב-%s כסיוע כאשר השרת הביתי שלך אינו מציע כזה (כתובת ה- IP שלך תשותף במהלך שיחה) + אפשר שרת עזרה לשיחות + השתמש ברינגטון ברירת המחדל של אלמנט לשיחות נכנסות + בקש אישור לפני שמתחילים בשיחה + מנע שיחה מקרית + שיחות + נושא החדר + שם חדר + היום + אתמול + %1$dm %2$ds + % d s + האם לבטל את ההעלאה\? + האם לבטל את ההורדה\? + קטן + בינוני + גדול + מקור + שלח כ + + שינוי בפרט חברות + שינוי בפרטי חברות + שינוי בפרטי חברות + שינוי בפרטי חברות + + רשימת קבוצות + קרא את רשימת הקבלות + הפעל את Element במכשיר אחר שיכול לפענח את ההודעה כדי שיוכל לשלוח את המפתחות להפעלה זו. + הבקשה נשלחה + בקשת המפתח נשלחה. + בקש מחדש מפתחות הצפנה מהפעלות האחרות שלך. + בטל הכל + שלח מחדש הכל + הודעות לא נשלחו בגלל הימצאות פעילויות לא ידועות. %1$s או %2$s עכשיו\? + הודעות לא נשלחו. %1$s או %2$s עכשיו\? + הקישוריות לשרת אבדה. + שלח תשובה (לא מוצפן) … + יעדי התראות + ניהול מפתחות קריפטוגרפיה + קריפטוגרפיה + השתמש במנהל שילוב לניהול בוטים, גשרים, ווידג\'טים וחבילות מדבקות. +\nמנהלי אינטגרציה מקבלים נתוני תצורה ויכולים לשנות ווידג\'טים, לשלוח הזמנות לחדר ולהגדיר רמות כוח מטעמכם. + אינטגרציות + מתקדם + אחר + משתמשים שמתעלמים מהם + התראות + הגדרות משתמש + נקה מטמון מדיה + נקה את זיכרון המטמון + שמור על מדיה + מדיניות הפרטיות + זכויות יוצרים + התראות צד שלישי + תנאים והגבלות + גרסת olm + גִרְסָה + + % d שנייה + % d שניות + % d שניות + % d שניות + + עיכוב בין כל סינכרון + %s +\nהסנכרון עשוי להידחות בהתאם למשאבים (סוללה) או מצב ההתקן (שינה). + מרווח סינכרון מועדף + פסק-זמן לבקשה לסנכרון + אפשר סנכרון רקע + החל באתחול + עדכון ההגדרות נכשל. + לא תקבל הודעה על הודעות נכנסות כאשר האפליקציה ברקע. + אין סנכרון רקע + אלמנט יסונכרן ברקע מעת לעת בזמן מדויק (ניתן להגדרה). +\nזה ישפיע על השימוש ברדיו ובסוללה, תוצג הודעה קבועה לפיה אלמנט מאזין לאירועים. + מותאם לזמן אמת + אלמנט יסונכרן ברקע באופן שישמור על המשאבים המוגבלים של המכשיר (סוללה). +\nבהתאם למצב משאבי המכשיר שלך, ייתכן שהסנכרון יידחה על ידי מערכת ההפעלה. + מותאם לסוללה + מצב סנכרון רקע + סנכרון רקע + הודעות שנשלחו על ידי בוט + הזמנות לשיחות + כשאני מוזמן לחדר + הודעות בצ\'אטים קבוצתיים + הודעות בצ\'אטים אחד-על-אחד + הודעות שמכילות את שם המשתמש שלי + הודעות שמכילות את שם התצוגה שלי + בחר צבע LED, רטט, צליל … + הגדר התראות שקטות + הגדר התראות על שיחות + הגדר תצורה של התראות רועשות + הדלק את המסך למשך 3 שניות + אפשר התראות עבור מושב זה + אפשר התראות עבור חשבון זה + צליל התראה + • התראות <b> לא יציגו את תוכן ההודעה </ b>not show message content + • התראות מכילות <b> נתוני ליבה והודעות </ b>meta and message data + • תוכן ההודעה של ההודעה <b> ממוקם בצורה מאובטחת ישירות משרת הבית של מטריקס </ b>located securely direct from the Matrix homeserver + • התראות מכילות רק נתוני ליבה + • התראות נשלחות באמצעות Firebase Cloud Messaging + היישומים <b> לא </ b> צריכים להתחבר ל- HomeServer ברקע, זה אמור להפחית את השימוש בסוללהnot need to connect to the HomeServer in the background, it should reduce battery usage + האפליקציה זקוקה לאישורך כדי לפעול ברקע + פרטיות מצומצמת + רגיל + התעלם מאופטימיזציה + אם משתמש משאיר מכשיר מחובר לחשמל ויציב לתקופה מסוימת, כשהמסך כבוי, המכשיר עובר למצב Doze. זה מונע מאפליקציות גישה לרשת ומגדיר את העבודות, הסנכרונים וההתראות הסטנדרטיות שלהם. + אלמנט אינו מושפע מתהליך מיטוב הסוללה. + אופטימיזציה של הסוללה + השבת הגבלות + מגבלות רקע מופעלות עבור Element. +\nהעבודה שהאפליקציה מנסה לעשות תוגבל באגרסיביות בזמן שהיא ברקע, וזה עלול להשפיע על ההודעות. +\n%1$s + מגבלות רקע מושבתות עבור Element. יש להריץ בדיקה זו באמצעות נתונים ניידים (ללא WIFI). +\n%1$s + בדוק מגבלות רקע + הפעל את התחלה לאחר אתחול + השירות לא יופעל עם הפעלת המכשיר מחדש, לא תקבל התראות עד שאלמנט ייפתח לפחות פעם אחת. + השירות יתחיל עם הפעלת המכשיר מחדש. + הפעל לאחר אתחול + השירות נכשל מלעלות מחדש + השירות נסגר והופעל מחדש אוטומטית. + הפעלה מחדש אוטומטית לשירות ההתראות + החל שירות + שירות ההתראות אינו פועל. +\nנסה להפעיל מחדש את היישום. + שירות ההתראות פועל. + שירות התראות + ההודעה נלחצה! + אנא לחץ על ההודעה. אם אינך רואה את ההודעה, אנא בדוק את הגדרות המערכת. + תצוגת התראות + אתה צופה בהודעה! לחץ עלי! + קבלת הדחיפה נכשלה. הפתרון יכול להיות התקנה מחדש של היישום. + בדיקת שליחה בדחיפה (PUSH) + היישום מקבל PUSH + היישום ממתין ל- PUSH + נכשל רישום אסימון FCM ל- HomeServer: +\n%1$s + אסימון FCM נרשם בהצלחה ל- HomeServer. + רישום אסימונים + הוסף חשבון + [%1$s] +\nשגיאה זו אינה בשליטה על אלמנט. אין חשבון Google בטלפון. אנא פתח את מנהל החשבון והוסף חשבון Google. + [%1$s] +\nשגיאה זו אינה בשליטה על אלמנט. זה יכול להתרחש מכמה סיבות. אולי זה יעבוד אם תנסה שוב מאוחר יותר, תוכל גם לבדוק ששירות Google Play אינו מוגבל בשימוש נתונים בהגדרות המערכת, או ששעון המכשיר שלך תקין, או שזה יכול לקרות ב- ROM מותאם אישית. + [%1$s] +\nשגיאה זו איננה בשליטה על Element ולפי גוגל, שגיאה זו מצביעה על כך שלמכשיר יש יותר מדי אפליקציות הרשומות ב- FCM. השגיאה מתרחשת רק במקרים שבהם ישנם מספרים קיצוניים של אפליקציות, כך שהיא לא אמורה להשפיע על המשתמש הממוצע. + נכשל באחזור אסימון FCM: +\n%1$s + אסימון FCM אוחזר בהצלחה: +\n%1$s + אסימון Firebase + תקן שירותי Google Play + אלמנט משתמש בשירותי Google Play כדי להעביר הודעות פוש אך נראה שהוא אינו מוגדר כהלכה: +\n%1$s + ה- APK של שירותי Google Play זמין ומעודכן. + בדיקת שירותי הפעלה + בדוק בהגדרות + טעינת הכללים המותאמים אישית נכשלה, אנא נסה שוב. + חדרים + אין תוצאות + סנן משתמשים מודרים + סנן חברים מהחדר + חפש + בטל הורדה + בטל העלאה + האם ברצונך להסתיר את כל ההודעות ממשתמש זה\? +\nשים לב שפעולה זו תפעיל מחדש את האפליקציה והיא עשויה להימשך זמן מה. + סיבה לדיווח על תוכן זה + הצטרף + מוזמן + תעודת זהות שגויה. צריכה להיות כתובת דוא\"ל או מזהה מטריצה כמו \'@localpart: domain\' + + % d נבחר + % d נבחרים + % d נבחרים + % d נבחרים + + הגדרות + קבצים + אנשים + פרטי החדר + קבל את האישור רק אם מנהל השרת פרסם טביעת אצבע התואמת את זו שלמעלה. + האישור השתנה מאישור מהימן בעבר לאיש מהימן. ייתכן שהשרת חידש את האישור שלו. פנה למנהל השרת לקבלת טביעת האצבע הצפויה. + האישור השתנה מאישור שהטלפון שלך אמין עליו. זה מאוד לא שגרתי. מומלץ לא לקבל את האישור החדש הזה. + אם מנהל השרת אמר שזה צפוי, ודא שטביעת האצבע שלמטה תואמת את טביעת האצבע שמספקת אותם. + יכול להיות שמישהו מיירט את התעבורה שלך בזדון, או שהטלפון שלך לא סומך על האישור שמספק השרת המרוחק. + לא ניתן לאמת את זהות השרת המרוחק. + טביעת אצבע (%s): + התעלם + יציאה + אל תתן אמון + אמון + + הודעה חדשה + הודעות חדשות + הודעות חדשות + הודעות חדשות + + אין לך הרשאה לפרסם בחדר זה + הקובץ לא נמצא + מחק הודעות שלא נשלחו + שלח שוב הודעות שלא נשלחו + שלח תשובה מוצפנת … + שלח הודעה (לא מוצפן) … + שלח הודעה מוצפנת … + %1$s &%2$s ואחרים מקלידים … + %1$s &%2$s מקלידים … + %s מקליד … + חפש + אימייל או מזהה מטריקס + אנא הזן כתובת דוא\"ל אחת או יותר או מזהה מטריקס + הזמן משתמש לפי מזהה + משתמשי מטריקס בלבד + אנשי קשר מקומיים (%d) + <u> הזמן לפי מזהה </ u>Invite by ID + %1$s %2$s + %1$s and %2$s + "%1$s, " + האם אתה בטוח שברצונך להזמין את%s לצ\'אט זה\? + סיבה + הסרת נידוי ממשתמש יאפשר לו להצטרף שוב לחדר. + איסור על המשתמש יבעט בהם מחדר זה וימנע מהם להצטרף שוב. + הסר נידוי ממשתמש + סיבות לנידוי + נדה משתמש + משתמש מעיף יסיר אותם מחדר זה. +\n +\nכדי למנוע מהם להצטרף שוב, עליך לאסור אותם במקום זאת. + סיבות להעפה + העף משתמש + האם אתה בטוח שברצונך לבטל את ההזמנה עבור משתמש זה\? + בטל הזמנה + הסרת התעלמות + ביטול חתימת משתמש זה יציג את כל ההודעות מהם שוב. + הסרת התעלמות ממשתמש + התעלם + התעלמות ממשתמש זה תסיר את ההודעות שלו מחדרים שאתה משתף. +\n +\nאתה יכול להפוך פעולה זו בכל עת בהגדרות הכלליות. + התעלם ממשתמש + לְהוֹרִיד בְּדַרגָה + לא תוכל לבטל את השינוי הזה מכיוון שאתה מוריד את עצמך בדרגה, אם אתה המשתמש המיועד האחרון בחדר, אי אפשר יהיה להחזיר לו הרשאות. + להוריד את עצמך\? + לא תוכל לבטל את השינוי הזה מכיוון שאתה מקדם את המשתמש לאותה רמת כוח כמוך. +\nהאם אתה בטוח\? + הצג רשימת מושבים + אזכר + מזהה משתמש, שם או דוא\"ל + הפוך למנהל + הפוך למנחה + אפס למשתמש רגיל + העף + הסרת התעלמות + התעלם + הסר מחדר זה + עזוב חדר זה + בטל הזמנה + הזמן + מושבים + הודעות ישירות + שיחה + כלי אדמיניסטרציה + זמין + אופליין + אונליין + צור + חלק מההתראות מושבתות בהגדרות המותאמות אישית שלך. + שים לב שחלק מסוגי ההודעות מוגדרים כשתיקים (יפיקו התראה ללא צליל). + הגדרות מותאמות אישית. + אפשר + התראות אינן מופעלות עבור הפעלה זו. +\nאנא בדוק את הגדרות האלמנט. + התראות מופעלות להפעלה זו. + הגדרות מושב. + אפשר + התראות מושבתות עבור חשבונך. +\nאנא בדוק את הגדרות החשבון. + התראות מופעלות עבור חשבונך. + הגדרות חשבון. + פתח את ההגדרות + התראות מושבתות בהגדרות המערכת. +\nאנא בדוק את הגדרות המערכת. + התראות מופעלות בהגדרות המערכת. + הגדרות מערכת. + בדיקה אחת או יותר נכשלו, אנא שלח דו\"ח שגיאה שיעזור לנו לחקור זאת. + בדיקה אחת או יותר נכשלו, נסה הצעה/ות אלו לתיקון. + אבחון בסיסי תקין. אם עדיין אינך מקבל התראות, אנא שלח דו\"ח שגיאה שיעזור לנו לחקור זאת. + הרץ מבדקים + אבחון לפתרון בעיות + פותר בעיות התראות + פרטיות הודעות + חשיבות ההודעה לפי אירוע + הגדרות התראה מתקדמות + וודא שלחצת על הקישור בהודעת הדוא\"ל ששלחנו אליך. + להסיר את%s\? + מספרי טלפון + לא הוספה כתובת דוא\"ל לחשבונך + כתובות דוא\"ל + נדרש אימות + אינך יכול לעשות זאת ממכשיר נייד + אשר את סיסמתך + הצג את פרטי היישום בהגדרות המערכת. + מידע על האפליקציה + הוסף מספר טלפון + לא הוסף מספר טלפון לחשבונך + מספר טלפון + הוסף כתובת דוא\"ל + כתובת דוא\"ל + שם תצוגה + תמונת פרופיל + מדיניות הפרטיות + זכויות יוצרים + התראות צד שלישי + תנאים והגבלות + גרסה + הגדרות + הודעות + הוסף למסך הבית + שכח + עזוב את השיחה + צ\'אט ישיר + בטל עדיפות + מועדף + השתק + אזכורים בלבד + כל ההודעות + כל ההודעות (קוליות) + מחפש בתיקייה… + + d% חדר + d% חדרים + d% חדרים + d% חדרים + + חפש בתיקיות + הקלד מזהה חדר או כינוי לחדר + הצטרף לחדר + הצטרף לחדר + צור חדר + התחלת שיחת צ\'אט + הזמנות + עדיפות נמוכה + חדרים + מועדפים + תיקייה ראשית + הצטרף + עדיין אין תמיכה בחיפוש בחדרים מוצפנים. + קבצים + אנשים + הודעות + האם אתה בטוח שברצונך להסיר את%s מהצ\'אט הזה\? + האם ברצונך לעזוב את החדר\? + עזוב חדר + + %dd + %dd + %dd + %dd + + + %dh + %dh + %dh + %dh + + + %dm + %dm + %dm + %dm + + + %ds + %ds + %ds + %ds + + חבר אחד + + חבר + חברים + חברים + חברים + + + חבר פעיל + חברים פעילים + חברים פעילים + חברים פעילים + + הוסף חבר + התחל אימות + מושב לא מאומת מבקש מפתחות הצפנה. +\nשם מושב: %1$s +\nנראה לאחרונה: %2$s +\nאם לא נכנסת למפגש אחר, התעלם מבקשה זו. + ההפעלה \'%s\' לא מאומתת מבקשת מפתחות הצפנה. + מושב חדש מבקש מפתחות הצפנה. +\nשם מושב: %1$s +\nנראה לאחרונה: %2$s +\nאם לא נכנסת למפגש אחר, התעלם מבקשה זו. + הוספת מושב חדש \'%s\', המבקש מפתחות הצפנה. + כדי להמשיך עליך לקבל את תנאי השירות הזה. + אפשרות זו מחייבת יישום צד שלישי להקליט את ההודעות. + שלח הודעות קוליות + השתמש במקש הזנת המקלדת כדי לשלוח הודעה + הפעל את מצלמת המערכת במקום את מסך המצלמה המותאם אישית. + השתמש במצלמה מקומית + אין יישומונים פעילים + נהל אינטגרציות + הוסף אפליקציות מטריקס + לא הוגדר מנהל אינטגרציה. + פרמטר אינו חוקי. + פרמטר חובה חסר. + החדר %s אינו גלוי. + חסר זהות משתמש בבקשה. + חסר מספר זהות חדר בבקשה. + אין לך אישור לעשות זאת בחדר זה. + אתה לא בחדר הזה. + רמת הרשאה חייבת להיות חיובית שלמה. + שליחת הבקשה נכשלה. + לא ניתן ליצור יישומון. + קרא מדיה מוגנת DRM + השתמש במיקרופון + השתמש במצלמה + חסום הכל + אפשר + יישומון זה רוצה להשתמש במשאבים הבאים: + מצטערים, שיחות ועידה עם Jitsi אינן נתמכות במכשירים ישנים (מכשירים עם מערכת הפעלה אנדרואיד מתחת ל -5.0) + מזהה חדר + מזהה ישומון + ערכת הנושא שלכם + מזהה המשתמש שלך + כתובת האתר של הדמות שלך + שם התצוגה שלך + בטל גישה עבורי + פתח בדפדפן + טען יישומון מחדש + השימוש בו עשוי לשתף נתונים עם %s: + השימוש בו עשוי להגדיר קובצי cookie ולשתף נתונים עם %s: + ישומון זה התווסף על ידי: + טען ישומון + ישומון + ישומונים פעילים + צפה + + %d יישומון פעיל + %d ישומונים פעילים + %d ישומונים פעילים + %d ישומונים אחרים פעילים + + האם אתה בטוח שברצונך למחוק את היישומון מחדר זה\? + צור שיחות ועידה עם jitsi + יצירת היישומון נכשלה + אתה זקוק להרשאה כדי לנהל יישומונים בחדר זה + ענק + הכי גדול + גדול יותר + גדול + רגיל + קטן + זעיר + גודל גופן + חפש היסטורי + %1$s: %2$s %3$s + %1$s:%2$s + ** השליחה נכשלה - אנא פתח את החדר + אני + הזמנות חדשות + הודעות חדשות + חדר + מאורע חדש + %1$s ו %2$s + %1$s ב %2$s ו %3$s + %1$s ב %2$s + + התראה %1$s: %2$d + התראות %1$s: %2$d + התראות מועטות %1$s: %2$d + התראות אחרות %1$s: %2$d + + + הודעה %1$s: %2$d + הודעות %1$s: %2$d + הודעות מעטות %1$s: %2$d + הודעות אחרות %1$s: %2$d + + + %d הזמנה + %d הזמנות + %d הזמנות מעטות + %d הזמנות אחרות + + + %d חדר + %d חדרים + %d חדרים מועטים + %d חדרים אחרים + + + %d הודעת התראה שלא נקראה + %d הודעות התראה שלא נקראו + %d הודעות התראה מעטות שלא נקראו + %d הודעות התראה אחרות שלא נקראו + + + הודעת התראה %d שלא נקראה + %d הודעות התראה שלא נקראו + %d הודעות התראה מעטות שלא נקראו + %d הודעות התראה אחרות שלא נקראו + + הקלד פה… + כל החדרים המקומיים %s + כל החדרים בשרת %s + כתובת אתר של שרת בית + הקלד שרת בית כדי לרשום ממנו חדרים ציבוריים + ייתכן שהשרת אינו זמין או עומס יתר + בחר מדריך חדרים + חדר זה מכיל פעילויות לא ידועות שלא אומתו. +\nהמשמעות היא שאין ערובה לכך שההפעלות שייכות למשתמשים שהם טוענים להם. +\nאנו ממליצים שתעבור את תהליך האימות של כל מפגש לפני שתמשיך, אך תוכל לשלוח שוב את ההודעה מבלי לאמת אם אתה מעדיף. +\n +\nהפעלות לא ידועות: + החדר מכיל הפעלות לא ידועות + אני מאשר שהמפתחות תואמים + אם הם לא תואמים, אבטחת התקשורת שלך עלולה להיפגע. + אשרו על ידי השוואה בין הדברים הבאים להגדרות המשתמש בפגישה האחרת שלכם: + אמת מושב + הסר מרשימה שחורה + רשימה שחורה + הסר אימות + אמת + ללא + IP לא ידוע + מושב לא ידוע + ברשימה שחורה + מאומת + לא תקין + + מפתח %1$d/%2$d מיובא בהצלחה. + מפתחות %1$d/%2$d יובאו בהצלחה. + מפתחות %1$d/%2$d מעטים יובאו בהצלחה. + מפתחות %1$d/%2$d אחרים יובאו בהצלחה. + + לעולם אל תשלח הודעות מוצפנות להפעלות לא מאומתות מהפגישה זו. + הצפן למפגשים מאומתים בלבד + יבא + ייבא את המפתחות מקובץ מקומי + ייבא מפתחות לחדר + ייבא מפתחות לחדר E2E + נהל גיבוי מפתח + שחזור הודעות מוצפנות + מפתחות יוצאו בהצלחה + מקשי החדר E2E נשמרו ב- \'%s\'. +\n +\nאזהרה: קובץ זה עשוי להימחק אם הסרת ההתקנה של היישום. + אנא צור משפט סיסמה להצפנת המפתחות המיוצאים. יהיה עליך להזין את אותו ביטוי סיסמה כדי שתוכל לייבא את המפתחות. + יצא + יצא מפתחות לקובץ מקומי + יצא מפתחות חדר + ייצא מפתחות חדר E2E + טביעת אצבע Ed25519 + אימות + מזהה מפתח + מזהה מושב + שם ציבורי + השם הציבורי של הפגישה גלוי לאנשים שאיתם אתה מתקשר + שם ציבורי (גלוי לאנשים שאיתם אתה מתקשר) + שם ציבורי + מידע על מושב השולח + שגיאת פענוח + מזהה מושב + מזהה משתמש + אַלגוֹרִיתְם + תביעת מפתח טביעת אצבע של Ed25519 + מפתח זהות Curve25519 + מידע על האירוע + מידע על הצפנה מקצה לקצה + %s ניסתה לטעון נקודה מסוימת בציר הזמן של החדר הזה אך לא הצליחה למצוא אותה. + ערכת נושא + מַדרִיך + אפשר הצפנה +\n(אזהרה: לא ניתן להשבית שוב!) + הצפנה מושבתת בחדר זה. + הצפנה מופעלת בחדר זה. + העתק כתובת חדר + העתק מזהה חדר + ביטול ההגדרה ככתובת הראשית + הגדר ככתובת ראשית + אזהרות כתובת עיקריות + לא תהיה לך כתובת ראשית שצוינה לחדר זה. + \'%s\' אינו פורמט חוקי לכינוי + פורמט כינוי לא חוקי + \'%s\' אינו מזהה קהילה חוקי + מזהה קהילה לא חוקי + מזהה קהילה חדש (למשל + foo: matrix.org) + חדר זה אינו מגלה כישרון בקרב קהילות כלשהן + כתובת חדשה (למשל #foo: matrix.org) + לחדר זה אין כתובות מקומיות + לעולם אל תשלח הודעות מוצפנות להפעלות לא מאומתות בחדר זה מהפגישה זו. + הצפן לביקורים מאומתים בלבד + עליך להתנתק כדי שתוכל לאפשר את ההצפנה. + הצפנה מקצה לקצה פעילה + הצפנה מקצה לקצה + אלה תכונות ניסיוניות שעשויות להישבר בדרכים לא צפויות. השתמש בזהירות. + מעבדות + כתובות + תעודת הזהות הפנימית של החדר הזה + מתקדם + משתמשים אסורים + כל מי שמכיר את הקישור לחדר, כולל אורחים + כל מי שמכיר את הקישור לחדר, מלבד האורחים + רק אנשים שהוזמנו + כדי לקשר לחדר חייבת להיות כתובת. + חברים בלבד (מאז שהצטרפו) + חברים בלבד (מאז שהוזמנו) + חברים בלבד (מאז נקודת הזמן לבחירת אפשרות זו) + כל אדם + לא ניתן לאחזר את הראות הנוכחית של ספריית החדרים (%1$s). + לפרסם את החדר הזה לציבור במדריך החדרים של %1$s\? + בטל את הפרסום של כתובת זו + פרסם כתובת זו + הוסף כתובת מקומית + לחדר זה אין כתובות מקומיות + הגדר כתובות לחדר זה כדי שמשתמשים יוכלו למצוא את החדר הזה דרך שרת הבית שלך (%1$s) + כתובות מקומיות + כתובת שפורסמה חדשה (למשל alias:server#) + עדיין אין כתובות שפורסמו. + עדיין אין כתובות שפורסמו, הוסף כתובת למטה. + פרסם חדר זה כציבורי ברשימת החדרים של \"%1$s\"\? + מחק את הכתובת \"%1$s\"\? + הסר פרסום של הכתובת \"%1$s\"\? + פרסם + פרסם כתובת חדשה באופן ידני + כתובות אחרות שפורסמו: + כתובת ראשית + זו הכתובת העיקרית + כל אחד מכל שרת יכול להשתמש בכתובות שפורסמו כדי להצטרף לחדר שלך. כדי לפרסם כתובת, תחילה יש להגדיר אותה ככתובת מקומית. + כתובות שפורסמו + כתובות חדרים + ראה וניהול כתובות של חדר זה, והנראות שלו בספריית החדרים. + כתובות החדר + גישה לחדר + מי יכול לגשת לחדר הזה\? + שינויים במי שיכול לקרוא היסטוריה יחולו רק על הודעות עתידיות בחדר זה. נראות ההיסטוריה הקיימת לא תשתנה. + מי יכול לקרוא היסטוריה\? + הקריאה בהיסטוריה של החדרים + גישה לחדר + התראות + רשום חדר זה ברשימת החדרים + כניסה ונראות + ללא + עדיפות נמוכה + מועדפים + תוייג כ-: + תגית חדר + נושא + שם חדר + תמונת חדר + לעד + חודש 1 + שבוע 1 + 3 ימים + אינכם חברים בשום קהילה. + כשרון + השמע צליל תריס + בחרו + מקור מדיה ברירת מחדל + בחרו + דחיסת ברירת מחדל + מדיה + מידע נוסף: %s + אירעה שגיאה במהלך אימות מספר הטלפון שלך. + קוד + שגיאה בעת אימות מספר הטלפון שלך + הזן קוד הפעלה + שלחנו SMS עם קוד הפעלה. אנא הזן קוד זה למטה. + אימות טלפון + מספר טלפון לא חוקי עבור המדינה שנבחרה + מספר טלפון + בבקשה בחרו מדינה + מדינה + בחר\\י מדינה + האם אתה בטוח שברצונך להסיר את %1$s %2$s \? + האם אתה בטוח שברצונך להסיר את יעד ההודעות הזה\? + נהל מיילים ומספרי טלפון המקושרים לחשבון מטריקס שלך + דוא\"ל ומספר טלפון + סיסמאות לא תואמות + הצג את כל ההודעות מ- %s\? +\n +\nשים לב שפעולה זו תפעיל מחדש את האפליקציה והיא עשויה להימשך זמן מה. + הסיסמה שלכם עודכנה + הסיסמה אינה תקינה + עדכון הסיסמה נכשל + עדכון סיסמה + אישור סיסמה חדשה + סיסמה חדשה + סיסמה נוכחית + שינוי סיסמה + סיסמה + הסתיים + שמור על מפתח התאוששות שלך במקום כלשהו מאובטח מאוד, כמו מנהל סיסמאות (או כספת) + מפתח השחזור שלך הוא רשת ביטחון - אתה יכול להשתמש בו כדי להחזיר את הגישה להודעות המוצפנות שלך אם תשכח את משפט הסיסמה שלך. +\nשמור על מפתח התאוששות שלך במקום כלשהו מאובטח מאוד, כמו מנהל סיסמאות (או כספת) + המפתחות שלך מגובים. + הצלחה! + (מתקדם) הגדר עם מפתח השחזור + לחלופין, אבטח את הגיבוי שלך באמצעות מפתח שחזור ושמור אותו במקום בטוח. + יוצר גיבוי + הגדר ביטוי + אנו נאחסן עותק מוצפן של המפתחות שלך בשרת הבית שלך. הגן על הגיבוי שלך באמצעות משפט סיסמה כדי לשמור על אבטחתו. +\n +\nליתר ביטחון, זה צריך להיות שונה מסיסמת החשבון שלך. + אבטח את הגיבוי שלך באמצעות משפט סיסמה. + ייצא ידנית מפתחות + (מתקדם) + התחל להשתמש בגיבוי מקשים + הודעות בחדרים מוצפנים מאובטחות באמצעות הצפנה מקצה לקצה. רק אתה והנמען / ים יש את המקשים לקריאת ההודעות האלה. +\n +\nגבה את המפתחות שלך בצורה מאובטחת כדי לא לאבד אותם. + לעולם אל תאבד הודעות מוצפנות + אין מושב מטריקס זמין + אנא מחק את משפט הסיסמה אם ברצונך ש- Element ייצור מפתח שחזור. + משפט הסיסמה חלש מדי + אנא הזן משפט סיסמה + משפט הסיסמה אינו תואם + הזן ביטוי סיסמה + אשר את ביטוי הסיסמה + צור ביטוי סיסמה + לא נמצא APK חוקי של שירותי Google Play. ייתכן שההודעות לא יפעלו כראוי. + %d+ + +%d + %1$s: %2$s + %1$s: + רק עבור שגיאות + עבור הודעות ושגיאות + לעולם + הראה את אזור המידע + כווץ + הרחב + סליחה, שגיאה התרחשה + שרת הבית שלך עדיין לא תומך בטעינה עצלה של חברי החדר. נסה מאוחר יותר. + הגדל את הביצועים רק על ידי חברי חדר העמסה בתצוגה הראשונה. + טעינה עצלה של חברים וחדרים + אנא %s להמשיך להשתמש בשירות זה. + אנא %s כדי להגדיל מגבלה זו. + שרת בית זה הגיע למגבלת המשתמשים הפעילים החודשיים שלו. + שרת בית זה הגיע למגבלת המשתמשים הפעילים החודשיים כך ש חלק מהמשתמשים לא יוכלו להתחבר . + שרת בית זה חרג מאחד ממגבלות המשאבים שלו. + שרת בית זה חרג מאחד ממגבלות המשאבים שלו כך ש משתמשים מסוימים לא יוכלו להתחבר . + פנה למנהל השירות שלך + צור קשר עם מנהל המערכת + לחץ כאן כדי לראות הודעות ישנות יותר ממגבלת המשאבים + לחץ כאן לצפייה בהודעות ישנות יותר + החדר הזה הוא המשך לשיחה אחרת + השיחה נמשכת כאן + חדר זה הוחלף ואינו פעיל יותר + אנא הזינו את סיסמה שלכם. + אהא הזינו שם משתמש. + השבת חשבון + להמשך, הזן את הסיסמה שלך: + אנא שכח את כל ההודעות ששלחתי כאשר חשבוני מושבת (אזהרה: הדבר יגרום למשתמשים עתידיים לראות תצוגה חלקית של השיחות) + זה יהפוך את חשבונך ללא שימוש לצמיתות. לא תוכל להתחבר, ואף אחד לא יוכל לרשום מחדש את אותו מזהה משתמש. הדבר יביא לחשבונך לעזוב את כל החדרים בהם הוא משתתף, והוא יסיר את פרטי חשבונך משרת הזהות שלך. פעולה זו היא בלתי הפיכה . +\n +\nהשבתת חשבונך אינה גורמת לנו כברירת מחדל לשכוח הודעות ששלחת . אם תרצה שנשכח את ההודעות שלך, סמן את התיבה למטה. +\n +\nנראות ההודעות במטריקס דומה לדוא\"ל. המשמעות של שכחת ההודעות שלך היא שהודעות ששלחת לא ישותפו עם משתמשים חדשים או לא רשומים, אך למשתמשים רשומים שכבר יש גישה להודעות אלה עדיין תהיה גישה להעתק שלהם. + השבת חשבון + בדוק כעת + כדי להמשיך להשתמש בשרת הבית %1$s עליך לבדוק ולהסכים לתנאים ולהגבלות. + אווטאר + אוואטר התרעה + אווטאר קבלה + שכח חדר + לָשׁוּב וֵלְהִצְטַרֵף + סיבה: %1$s + חסום על ידי %2$s מ- %1$s + אתה נבעט מ- %1$s על ידי %2$s + מנהל הקהילה לא סיפק תיאור ארוך לקהילה זו. + + חדר %d + %d חדרים + %d חדרים + %d חדרים אחרים + + + חבר %d + %d חברים + %d חברים + %d חברים אחרים + + סנן קבוצות חדרים + סנן חברי קבוצה + הוזמנו + הצתרפו + חדרים + אין משתמשים + חדרים + אנשים + בית + דוגמא + מזהה קהילה + דוגמא + שם הקהילה + צור קהילה + צור + הודעה מוצפנת + רועש + שקט + כבוי + סימון ההפעלה הושבת. + סימון ההפעלה הופעל. + כדי לתקן את ניהול אפליקציות מטריקס + הפעלה / כיבוי של סימון MARKDOWN + משנה את כינוי התצוגה שלך + בועט משתמש עם מזהה נתון + הגדר את נושא החדר + עזוב חדר + מצטרף לחדר עם כינוי נתון + מזמין משתמש עם זיהוי נתון לחדר הנוכחי + משתמש מבוטל עם מזהה נתון + הגדר את רמת ההרשאה של המשתמש + הסר חסימה למשתמש עם מזהה נתון + חסום משתמש עם מזהה נתון + הצג פעולה + הפקודה \"%s\" זקוקה ליותר פרמטרים, או שחלק מהפרמטרים שגויים. + פקודה לא מוכרת: %s + שגיאת פקודה + שיחת ועידה נמצאת בפיתוח ואולי לא אמינה. + אזהרה! + התעלם + התעלם מהבקשה + בקשה לשיתוף מפתח + שיתוף + שתף ללא אימות + אמת + כפתור Enter על המקלדת הרכה ישלח הודעה במקום להוסיף מעבר שורה + שלח הודעה עם Enter + הצג תצוגה מקדימה של מדיה לפני השליחה + רטוט בעת אזכור משתמש + כולל שינויים באווטאר ושמות תצוגה. + הצג אירועי חשבון + הזמנות, בעיטות ואיסורים אינם מושפעים. + הראה אירועי הצטרפות ועזיבה + כולל אירועי הזמנה / הצטרפות / שמאל / בעיטה / איסור ושינוי שם אווטאר / תצוגה. + הצג אירועים של מדינת החברים בחדר + לחץ על אישורי הקריאה לרשימה מפורטת. + הצג קבלות הצג קבלות קריאה + הצג חותמות זמן בפורמט של 12 שעות + הצג חותמות זמן לכל ההודעות + עצב הודעות באמצעות תחביר הסימון לפני שהן נשלחות. זה מאפשר עיצוב מתקדם כגון שימוש בכוכביות להצגת טקסט נטוי. + עיצוב Markdown + הודע למשתמשים אחרים שאתה מקליד. + שלח הודעות הקלדה + תצוגה מקדימה של קישורים בצ\'אט כאשר שרת הבית שלך תומך בתכונה זו. + תצוגה מקדימה של כתובת אתר מוטמעת + מושבים + הצמד חדרים עם הודעות שלא נקראו + הצמד חדרים עם התראות שלא נענו + ארץ ספר הטלפונים + מסך ראשי + הרשאת אנשי קשר + אנשי קשר מקומיים + לעולם אל תאבד הודעות מוצפנות + להגן מפני אובדן גישה להודעות ונתונים מוצפנים + גיבוי מאובטח + התחל להשתמש בגיבוי מפתח + לעולם אל תאבד הודעות מוצפנות + זה היה אני + גיבוי מפתח חדש גיבוי חדש של מפתח הודעות מאובטח. +\n +\nאם לא הגדרת את שיטת השחזור החדשה, ייתכן שתוקף מנסה לגשת לחשבונך. שנה את סיסמת החשבון שלך והגדר מיד שיטת שחזור חדשה בהגדרות. + גיבוי מפתח חדש + מחק גיבוי למחוק את מפתחות ההצפנה המגובים שלך מהשרת\? לא תוכל עוד להשתמש במפתח השחזור שלך כדי לקרוא את היסטוריית ההודעות המוצפנת. + מחק את הגיבוי + בודק מצב גיבוי + מחיקת הגיבוי נכשלה (%s) + מוחק גיבוי … + כדי להשתמש בגיבוי מקשים בהפעלה זו, שחזר באמצעות משפט הסיסמה או מפתח השחזור שלך כעת. + נכשל קבלת פרטי אמון לגיבוי (%s). + לגיבוי יש חתימה לא חוקית מהפעלה %s לא מאומתת + לגיבוי יש חתימה לא חוקית מההפעלה %s המאומתת + לגיבוי יש חתימה חוקית מהפעלה %s לא מאומתת + לגיבוי יש חתימה מהפעלה לא ידועה עם מזהה %s. + לגיבוי יש חתימה חוקית מההפעלה המאומתת %s. + לגיבוי יש חתימה חוקית מהפגישה זו. + לא מגובים את המפתחות שלך מהפגישה זו. + גיבוי המפתח אינו פעיל בהפעלה זו. + גיבוי המפתח הוגדר כהלכה להפעלה זו. + מחק את הגיבוי + שחזר מגיבוי + הצפנת מושב אינה מופעלת + השגת הגרסה האחרונה של מפתחות השחזור (%s) נכשלה. + הגיבוי שוחזר %s! + לא ניתן היה לפענח את הגיבוי באמצעות מפתח שחזור זה: ודא שהזנת את מפתח השחזור הנכון. + אנא הכנס מפתח שחזור + בטל נעילת היסטוריה + מייבא מפתחות … + מוריד מקשים … + מפתח שחזור מחשוב … + שחזור הגיבוי: + שגיאת רשת: אנא בדוק את החיבור שלך ונסה שוב. + לא ניתן לפענח גיבוי באמצעות ביטוי סיסמה זה: אנא ודא שהזנת את ביטוי הסיסמה לשחזור הנכון. + איבדת את מפתח ההתאוששות שלך\? אתה יכול להגדיר אחד חדש בהגדרות. + שחזור הודעות + הזן מפתח שחזור + השתמש במפתח השחזור שלך כדי לפתוח את היסטוריית ההודעות המוצפנות שלך + אינך יודע את ביטוי הסיסמה לשחזור שלך, אתה יכול %s. + השתמש במפתח השחזור שלך + השתמש בביטוי הסיסמה לשחזור כדי לבטל את נעילת היסטוריית ההודעות המוצפנות שלך + מביא גרסת גיבוי … + אתה עלול לאבד גישה להודעות שלך אם אתה מתנתק או מאבד מכשיר זה. + האם אתה בטוח\? + מפתחות ההצפנה שלך מגובים כעת ברקע לשרת הבית שלך. הגיבוי הראשוני עשוי להימשך מספר דקות. + הגיבוי התחיל + שגיאה לא צפויה + מפתח שחזור + יצירת מפתח שחזור באמצעות ביטוי סיסמה, תהליך זה יכול להימשך מספר שניות. + שתף מפתח שחזור עם … + בבקשה צרו העתק + עצור + החלפה + נראה שכבר יש לך גיבוי מפתח הגדרה מהפעלה אחרת. האם אתה רוצה להחליף אותו לזה שאתה יוצר\? + גיבוי כבר קיים בשרת הבית שלך + מפתח השחזור נשמר. + מפתח השחזור נשמר ב- \'%s\'. +\n +\nאזהרה: קובץ זה עשוי להימחק אם הסרת ההתקנה של היישום. + שמירת קובץ בשם + שיתוף + שמור מפתח שחזור + הכנתי עותק + \ No newline at end of file diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 60171a30d1..29d77ad6d4 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -426,7 +426,7 @@ Vedd figyelembe, hogy az alkalmazás újraindul ami sok időt vehet igénybe."< Hozzáférés és láthatóság Listázza ezt a szobát a szoba listában Szoba hozzáfárés - Szoba előzmény olvashatósága + Üzenet előzmények láthatósága Ki tud előzményt olvasni? Ki tud hozzáférni a szobához? Bárki @@ -914,8 +914,7 @@ Bármi amit a Element el akar végezni amíg a háttérben fut, agresszívan kor Ha a felhasználó töltés nélkül kikapcsolt képernyővel egy ideig magára hagyja az eszközt, az eszköz „Doze” módba kerül. Ez megakadályozza az alkalmazás számára, hogy hozzáférjen a hálózathoz, nem engedi elvégezni a feladatait, szinkronizációt és az alapértelmezett riasztásait. Optimalizáció figyelmen kívül hagyása Háttér kapcsolat - Elementnak szüksége van egy minimális háttér kapcsolat fenntartására ahhoz, hogy az értesítések biztonságban megérkezhessenek. -A következő képernyőn el kell fogadnod, hogy a Element folyamatosan fusson a háttérben. + Az Elementnek szüksége van egy minimális háttér kapcsolat fenntartására ahhoz, hogy az értesítések megbízhatóan megérkezhessenek. A következő képernyőn el kell fogadnod, hogy a Element folyamatosan fusson a háttérben. Jogosultság megadása Az e-mail címed ellenőrzésekor hiba történt. A telefonszámod ellenőrzésekor hiba történt. @@ -951,7 +950,7 @@ Ez a hiba a Elementon kívül van. Nincs Google fiók az eszközön. Kérlek nyi Kérlek adj meg egy jelmondatot A jelmondat túl gyenge Ha azt szeretnéd, hogy a Element Visszaállítási Kulcsot generáljon akkor kérlek töröld a jelmondatot. - Jelenleg nincs Matrix kapcsolat + Jelenleg nincs Matrix munkamenet Soha ne veszíts el titkosított üzenetet A titkosított szobákban az üzenetek végponttól-végpontig titkosítva vannak. Csak neked és a címzetteknek vannak meg az üzenet elolvasásához szükséges kulcsok. @@ -996,7 +995,7 @@ Figyelmeztetés: ez a fájl törlésre kerülhet, ha az alkalmazást törlik.%d új kulcs lett hozzáadva ehhez a munkamenet. "Nem sikerült beszerezni a legfrissebb verziójú visszaállítási kulcsot (%s)." - Kapcsolat titkosítás nincs enegedélyezve + Munkamenet titkosítás nincs aktiválva Visszaállítás mentésből Mentés törlése A Kulcs mentés megfelelően be van állítva ezen a munkameneten. @@ -1248,7 +1247,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Beszélgetések szűrése… Nem találod amit keresel\? Új szoba készítése - Új közvetlen üzenet küldése + Új közvetlen beszélgetés indítása Szoba lista megjelenítése Név vagy azonosító (#pelda:matrix.org) Válasz engedélyezése húzással az idővonalon @@ -1283,7 +1282,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Állíts be egy e-mail címet fiók visszaállításhoz, és hogy később megtalálhassanak akik ismernek. Állíts be egy telefonszámot, hogy megtalálhassanak akik ismernek. Állíts be egy e-mail címet fiók visszaállításhoz. E-mail vagy telefonszám alapján megtalálhatnak akik ismernek. - Állíts be egy e-mail címet fiók visszaállításhoz. Később e-mail vagy telefonszám alapján megtalálhatnak akik ismernek. + Állíts be egy e-mail címet fiók visszaállításhoz. Később e-mail vagy telefonszám alapján megtalálhatnak az ismerőseid. Nem érhető el Matrix-kiszolgáló ezen a címen, ellenőrizd Tartalék hívássegítő kiszolgáló engedélyezése Segítőként a(z) %s lesz használatban ha a Matrix-kiszolgálója nem biztosít egyet (a hívás ideje alatt az IP-címed megosztásra kerül) @@ -1333,7 +1332,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Kibővített naplózás engedélyezése. A kiterjesztett naplózás a fejlesztőknek nyújt több információt amikor hibajegyet küldesz. Még bekapcsolva sem naplóz üzenet tartalmat vagy más személyes adatot. Kérlek ismételd meg miután elfogadtad a matrix szervered felhasználási feltételeit. - Úgy tűnik a szerver sokáig nem válaszol, ennek a bizonytalan kapcsolat vagy egy hiba a szerverünkben lehet az oka. Kicsit később próbáld újra. + Úgy tűnik a szerver sokáig nem válaszol, ennek a gyenge kapcsolat vagy szerverhiba lehet az oka. Próbáld újra később! Csatolmány küldése Navigációs panel megnyitása Szoba készítés menü megnyitása @@ -1354,7 +1353,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró \'%1$s\' (%2$s) fájl túl nagy a feltöltéshez. A korlát: %3$s. A csatolmány letöltésénél hiba történt. Fájl - Kapcsolat + Névjegy Kamera Hang Galéria @@ -1801,7 +1800,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Titkosítás nincs engedélyezve A szobában használt titkosítás nem támogatott %s elkészítette és beállította a szobát. - Majdnem kész! A többi eszközöd is ugyanazt a pajzsot mutatja\? + Majdnem kész! A másik eszközöd is ugyanazt a pajzsot mutatja\? Majdnem kész! Várakozás a megerősítésre… Várakozás erre: %s… A kulcsok betöltése sikertelen @@ -1865,7 +1864,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Kérlek válasz felhasználói nevet. Kérlek válassz jelszót. Ezt a hivatkozást ellenőrizd le még egyszer - A közvetlen üzenetedet nem sikerült elkészíteni. Ellenőrizd azokat a felhasználókat akiket meg szeretnél hívni és próbáld újra. + A közvetlen beszélgetést nem sikerült létrehozni. Ellenőrizd azokat a felhasználókat akiket meg szeretnél hívni és próbáld újra. "Használd a legújabb Elementet a többi eszközödön, azaz az Element Webet, az Element Desktopot, az Element for Androidot vagy más eszközök közötti hitelesítést támogató Matrix-klienst" Erősítsd meg ebben a bejelentkezésben a személyazonosságodat egy másik munkamenetből, hogy hozzáférhess a titkosított üzenetekhez. %1$s hivatkozás egy másik oldalra visz: %2$s. @@ -2115,4 +2114,40 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Email címek Még nem adtál hozzá telefonszámot a fiókodhoz Az üzenetek ebben a szobában végpontok közötti titkosítással védettek. + Kép hozzáadása + Adj meg egy témát + %s, hogy a többiek tudják, miről van szó ebben a szobában! + Felhasználók meghívása + Ez a közvetlen beszélgetés kezdete %s felhasználóval. + Itt kezdődik ez a beszélgetés. + Ez a %s szoba kezdete. + Ismert felhasználók + Keresés névvel, vagy Matrix ID-vel + Reakció: %s + Hozzáadás + Befejezés + Nincs jogosultságod hívást indítani + Nincs jogosultságod hívást indítani ebben a szobában + Mutasd meg ezt a kódot az ismerőseidnek, hogy be tudják olvasni, és elkezdődhessen a csevegés! + 🔐️ Csatlakozz hozzám Element-en + Hey, beszélgessünk Element-en: %s + Ismerősök meghívása + Saját kódom + Saját kód megosztása + Ez nem egy érvényes Matrix QR kód + QR kód nem lett beolvasva! + Érvénytelen QR kód (Érvénytelen URI)! + QR kód beolvasása + Új privát beszélgetés létrehozása QR kód beolvasásával + QR kód + Meghívás QR kóddal + A QR kód beolvasásához szükség van kamera hozzáférésre. + Engedélyezi, hogy elküldjük az névjegyek adatait (telefonszámok és/vagy e-mail címek) a beállított Azonosítási Szervernek (%1$s)\? +\n +\nAz adatvédelem érdekében az elküldés előtt egyirányú titkosítással (hasheléssel) lesz védve az elküldött adat. + Elutasítás + Fogadás + Nincsen jogosultságod konferenciahívás indításához + Csevegés indítása + Visszaállítás \ No newline at end of file diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 557aca192f..9c8c218a96 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -1233,9 +1233,9 @@ Benvenuti a casa! Recupera i messaggi non letti qui Conversazioni - Le tue conversazioni dirette verranno mostrate qui + Le tue conversazioni dirette verranno mostrate qui. Tocca il pulsante + per iniziarne qualcuna. Stanze - Le tue stanze verranno mostrate qui + Le tue stanze verranno mostrate qui. Tocca il pulsante + per trovare quelle esistenti o crearne di nuove. Reazioni D\'accordo Piace @@ -2309,4 +2309,37 @@ Per scansionare un codice QR, devi permettere l\'accesso alla fotocamera. Permetti l\'autorizzazione per l\'accesso ai contatti. Inizia a chattare + Cambia il tuo PIN attuale + Cambia PIN + Anteprima della stanza non disponibile. Vuoi entrare\? + Questa stanza non è accessibile al momento. +\nRiprova più tardi, o chiedi ad un admin della stanza di controllare se ne hai l\'accesso. + Impossibile rilevare l\'attuale visibilità dell\'elenco di stanze (%1$s). + Pubblicare questa stanza nell\'elenco pubblico delle stanze di %1$s\? + Revoca questo indirizzo + Pubblica questo indirizzo + Aggiungi un indirizzo locale + Questa stanza non ha indirizzi locali + Imposta gli indirizzi per la stanza affinché gli utenti la trovino attraverso il tuo homeserver (%1$s) + Indirizzi locali + Nuovo indirizzo pubblicato (es. #alias:server) + Nessun altro indirizzo ancora pubblicato. + Nessun altro indirizzo ancora pubblicato, aggiungine uno sotto. + Pubblicare questa stanza nell\'elenco pubblico delle stanze di %1$s\? + Eliminare l\'indirizzo \"%1$s\"\? + Revocare la pubblicazione dell\'indirizzo \"%1$s\"\? + Pubblica + Pubblica un nuovo indirizzo manualmente + Altri indirizzi pubblicati: + Indirizzo principale + Questo è l\'indirizzo principale + Gli indirizzi pubblicati possono essere usati da chiunque su qualsiasi server per entrare nella stanza. Per pubblicare un indirizzo, deve essere prima impostato come indirizzo locale. + Indirizzi pubblicati + Indirizzi stanza + Vedi e gestisci gli indirizzi di questa stanza e la sua visibilità nell\'elenco delle stanze. + Indirizzi stanza + Accesso alla stanza + La leggibilità della cronologia sarà modificata solo per i futuri messaggi di questa stanza. La visibilità dei messaggi esistenti rimarrà invariata. + Revoca pubblicazione + Aggiungi \ No newline at end of file diff --git a/vector/src/main/res/values-iw/strings.xml b/vector/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..dbfd579ba6 --- /dev/null +++ b/vector/src/main/res/values-iw/strings.xml @@ -0,0 +1,1288 @@ + + + התראות + כפתורי ניווט תחתונים + הצלחה + שגיאה + אזהרה + אישור + השבת + העתק ללוח הגזירים + הסר פרסום + הוסף + העתק + סגור + סמן כ\'נקרא\' + תגובה מהירה + היסטורי + סמן הכל כ\'נקרא\' + חיפוש כללי + שיחת וידאו + שיחה קולית + האם אתה בטוח שברצונך לצאת מחשבונך\? + יציאה מהחשבון + פעולות + יציאה + נתק + להסיר + לקבל + יְרִידָה + סקירה + להתעלם + לְהַפִּיל + בוצע + לדלג + לְקַבֵּל + לא מקוון + להזמין + לשלוח בכל מקרה + תתקשר בכל מקרה + שיחות ועידה אינן נתמכות בחדרים מוצפנים + הסרת היישומון נכשלה + הוספת היישומון נכשלה + מידע על מושב + אתה לא יכול להתקשר עם עצמך, לחכות שהמשתתפים יקבלו את ההזמנה + אינך יכול להתקשר עם עצמך + לא ניתן להתחיל להתקשר + הפגישות משתמשות במדיניות האבטחה וההרשאה של Jitsi. כל האנשים שנמצאים כעת בחדר יראו הזמנה להצטרף בזמן שהפגישה שלך מתרחשת. + התחל פגישת שמע + התחל פגישת וידאו + ועידה כבר בעיצומה! + אין לך הרשאה להתחיל שיחה + אין לך הרשאה להתחיל שיחה בחדר זה + אין לך הרשאה להתחיל שיחת ועידה + אין לך הרשאה להתחיל שיחת ועידה בחדר זה + אתה זקוק להרשאה כדי להזמין כדי להתחיל כנס בחדר זה + בגלל הרשאות חסרות, פעולה זו אינה אפשרית. + בגלל הרשאות חסרות, ייתכן שחלק מהתכונות חסרות … + לא יכול להתחיל את השיחה, נסה שוב מאוחר יותר + וידאו + קול + התחל לצ\'וטט + אתחול + השהה + לנגן + שיחה פעילה + דווח על תוכן + התנתק + לבטל + אין + שנה שם + מחק + צפה במקור המפוענח + צפה במקור הדף + קישור קבוע + העבר + מאוחר יותר + ניקוי + דבר + שתף + הורדה + צטט + הסר + שלח שוב + שלח + הישאר + עזיבה + שמירה + ביטול + אוקיי + טוען… + רישיונות צד ג \' + תאבד את הגישה להודעות המוצפנות שלך אלא אם כן תגבה את המפתחות לפני היציאה. + גבה + האם אתה בטוח\? + השתמש בגיבוי מפתח + מגבה מקשים … + אני לא רוצה את ההודעות המוצפנות שלי + גיבוי מפתח מאובטח צריך להיות פעיל בכל ההפעלות שלך כדי למנוע אובדן גישה להודעות המוצפנות שלך. + גיבוי המפתח מתבצע. אם תצא עכשיו תאבד את הגישה להודעות המוצפנות שלך. + אם תצא עכשיו, תאבד את ההודעות המוצפנות שלך + קישור למטריקס + או + פתיחה + כניסה + שחרר + גיבוי המפתחות לא הסתיים, אנא המתן … + אמת מושב + השתמש במפתח גיבוי + גיבוי מפתח + שלח מדבקה + פרטי קהילה + דיווח תקלות + הסטוריה + פרטי משתמש + הגדרות + חדר + הודעות + התראות שקטות + התראות רועשות + האזנה לאירועים + מסנכרן… + אתחול השירות + ערכת נושא Status.im + ערכת נושא שחורה + ערכת נושא כהה + ערכת נושא בהירה + Hebr + IL + iw + + משתמש %d + %d משתמשים + מעט + אחר + + אין חדרים ציבורים + אין חדרים + רשימת חדרים + חדרים + אין שיחות + אנשי קשר מטריקס בלבד + תיקיית האב של המשתמש + פנקס כתובות מקומי + שיחות + התראות מערכת + בעדיפות נמוכה + הזמנות + סנן שמות מבין רשימת הקהילות + סנן מבין רשימת החדרים + סנן מבין רשימת האנשים + סנן מהמועדפים + סנן שמות חדרים + קהילות + חדרים + לא הוגדר שרת זהות. + אין תוצאות נוספות + אין תוצאות + לא אפשרת לאלמנט לגשת לאנשי הקשר המקומיים שלך + האם אתה בטוח שברצונך להתחיל צ\'אט חדש עם %s\? + שלח קול + התחל שיחת וידאו + התחל שיחה קולית + התחל צ\'אט חדש + חיפוש + קישור לשרת הזיהוי + קישור לשרת הבית + יציאה + כניסה + צור חשבון + שם משתמש + הצטרף אל חדר + קרא + שלח פנימה + לא ניתן היה לשלוח את דוח הבאג (%s) + דוח הבאג נשלח בהצלחה + טלטול זעם כדי לדווח על באג + היישום התרסק בפעם האחרונה. האם ברצונך לפתוח את מסך דוח הקריסה\? + נראה שאתה מטלטל את הטלפון בתסכול. האם ברצונך לפתוח את מסך דוח הבאג\? + על מנת לאבחן בעיות, יומני הלקוח יישלחו עם דוח הבאג הזה. דוח באגים זה, כולל היומנים וצילום המסך, לא יהיה גלוי לציבור. אם אתה מעדיף לשלוח רק את הטקסט למעלה, בטל את הסימון: + תאר את הבעיה שלך כאן + אם אפשר, אנא כתוב את התיאור באנגלית. + אנא תאר את הבאג. מה עשית\? מה ציפית שיקרה\? מה באמת קרה\? + דווח על באג + שלח צילום מסך + שלח היסטוריית בקשות לשיתוף מפתח + שלח יומני תקלות + שלח יומנים + אין קבוצות + קהילות + הזמנה + שם משתמש זה כבר בשימוש + יותר מדי בקשות נשלחו + לא מכיל JSON חוקי + JSON פגום + אסימון הגישה שצוין לא זוהה + שם משתמש / סיסמא שגויים + המכשיר שלך משתמש בפרוטוקול אבטחה TLS מיושן, הפגיע להתקפה, למען ביטחונך לא תוכל להתחבר + שגיאת SSL. + שגיאת SSL: זהות העמית לא אומתה. + לא ניתן להגיע לשרת בית בכתובת אתר זו, אנא בדוק זאת + זו אינה כתובת שרת מטריקס חוקית + לא ניתן להגיע לכתובת אתר זו, אנא בדוק אותה + אנא הכנס כתובת תקינה + לא ניתן להירשם: כשל בבעלות על דוא\"ל + לא ניתן להירשם + לא ניתן להירשם: שגיאת רשת + לא מצליח להתחבר + לא ניתן להתחבר: שגיאת רשת + כתובת האתר חייבת להתחיל ב- http [s]: // + אנא עיין וקבל את המדיניות של שרת בית זה: + הסיסמה שלך אופסה. +\n +\nהוצאת מכל ההפעלות ולא תקבל עוד התראות דחיפה. כדי להפעיל מחדש התראות, התחבר מחדש בכל מכשיר. + אימות כתובת הדוא\"ל נכשל: ודא שלחצת על הקישור בדוא\"ל + דוא\"ל נשלח אל%s. לאחר שתעקוב אחר הקישור שהוא מכיל, לחץ למטה. + יש להזין סיסמה חדשה. + יש להזין את כתובת הדוא\"ל המקושרת לחשבונך. + כדי לאפס את הסיסמה שלך, הזן את כתובת הדוא\"ל המקושרת לחשבונך: + אימתתי את כתובת הדוא\"ל שלי + שרת זיהוי: + שרת הבית: + שם משתמש כבר נמצא בשימוש + שרת בית זה רוצה לוודא שאתה לא רובוט + הרשמה באמצעות דוא\"ל ומספר טלפון בבת אחת עדיין אינה נתמכת עד להתקנת ה- API. רק מספר הטלפון ייקח בחשבון. +\n +\nתוכל להוסיף את הדוא\"ל שלך לפרופיל שלך בהגדרות. + אנא בדוק את הדוא\"ל שלך כדי להמשיך בהרשמה + השתמש באפשרויות שרת מותאמות אישית (מתקדם) + שכחת סיסמה\? + סיסמא אינה תואמת לקודמתה + מטבע אינו חוקי + כתובת דוא\"ל או מספר טלפון חסרים + מספר טלפון חסר + כתובת דוא\"ל חסרה + מספר הטלפון הזה כבר קיים ומעודכן במערכת. + כתובת הדוא\"ל הזו כבר קיימת ומוגדרת במערכת. + זה אינו נראה כמספר טלפון חוקי + זה לא נראה כמו כתובת דוא\"ל חוקית + סיסמה חסרה + סיסמה קצרה מדי (נדרש לפחות 6 תווים) + שמות משתמשים עשויים להכיל רק אותיות, מספרים, נקודות, מקפים וקו תחתון + שם משתמש ו/או סיסמה לא נכונים + אשר את סיסמתך החדשה + חזור על הסיסמה + מספר טלפון (אופציונלי) + מספר טלפון + כתובת דוא\"ל (אופציונלי) + כתובת דוא\"ל + הגדר דוא\"ל לשחזור חשבון. השתמש באימייל או בטלפון מאוחרים יותר כדי שאפשר יהיה לגלות אותו על ידי אנשים שמכירים אותך. + הגדר דוא\"ל לשחזור חשבון. השתמש באימייל או בטלפון מאוחרים יותר כדי שאפשר יהיה לגלות אותו על ידי אנשים שמכירים אותך. + הגדר טלפון, ואחר כך יהיה ניתן לגלות אותו על ידי אנשים שמכירים אותך. + הגדר דוא\"ל לשחזור חשבון, ומאוחר יותר כך שניתן יהיה לגלות אותו על ידי אנשים שמכירים אותך. + שם משתמש + סיסמה חדשה + סיסמה + מייל או שם משתמש + חזור למסך כניסה + שלח מייל איפוס + דלג + הגש + צור חשבון + היכנס באמצעות כניסה יחידה + היכנס + מצטערים, לא נמצאה יישום חיצוני להשלמת פעולה זו. + המשך עם… + כרגע אין לך חבילות מדבקה מופעלות. +\n +\nלהוסיף כמה עכשיו\? + צלם סרטון + צלם תמונה + צלם תמונה או סרטון + שלח סטיקר + שלח קבצים + הפעל מצב HD + כבה מצב HD + אחורה + קדימה + החלף בין מצלמה + אוזניות אלחוטיות + אוזניות + רמקול + טלפון + בחר מכשיר סאונד + נכשל החיבור בזמן אמת. +\nאנא בקש ממנהל שרת הבית שלך להגדיר שרת TURN על מנת שהשיחות יעבדו בצורה אמינה. + שיחת האלמנט נכשלה + אל תשאל אותי שוב + נסה להשתמש ב-%s + השיחה נכשלה עקב שרת שהוגדר כהלכה + האם אתה בטוח שברצונך להתחיל שיחת וידאו\? + האם אתה בטוח שברצונך להתחיל שיחה קולית\? + צ\'ט חדש + הוסף שרת זהות בהגדרות שלך כדי לבצע פעולה זו. + זו תצוגה מקדימה של החדר הזה. אינטראקציות בחדר הושבתו. + חדר + אתה מנסה לגשת ל-%s. האם תרצה להצטרף על מנת להשתתף בדיון\? + הזמנה זו נשלחה אל%s, שאינה משויכת לחשבון זה. +\nייתכן שתרצה להתחבר עם חשבון אחר, או להוסיף דוא\"ל זה לחשבונך. + הוזמנת להצטרף לחדר זה על ידי%s + קפיצה להודעה הראשונה שלא נקראה. + מסנכרן… + פתח כותרת + חברי רשימה + דחייה + תצוגה מקדימה + הצטרף + הסר + המשך + לא!! + כן! + שמור להורדות\? + נשמר + אפשר הרשאה לגשת לאנשי הקשר שלך. + כדי לסרוק קוד QR, עליך לאפשר גישה למצלמה. + מצטער. הפעולה לא בוצעה בגלל הרשאות חסרות + אלמנט יכול לבדוק את פנקס הכתובות שלך כדי למצוא משתמשי מטריקס אחרים על סמך מספרי הדוא\"ל והטלפון שלהם. +\n +\nהאם אתה מסכים לשתף את פנקס הכתובות שלך למטרה זו\? + אלמנט יכול לבדוק את פנקס הכתובות שלך כדי למצוא משתמשי מטריקס אחרים על סמך מספרי הדוא\"ל והטלפון שלהם. אם אתה מסכים לשתף את פנקס הכתובות שלך למטרה זו, אנא הגש גישה בחלון הקופץ הבא. + אלמנט זקוק להרשאה כדי לגשת למצלמה ולמיקרופון שלך כדי לבצע שיחות וידאו. +\n +\nאנא אפשר גישה בחלונות הקופצים הבאים כדי להיות מסוגל לבצע את השיחה. + " +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לבצע את השיחה." + אלמנט זקוק להרשאה כדי לגשת למיקרופון שלך כדי לבצע שיחות שמע. + " +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לבצע את השיחה." + אלמנט זקוק להרשאה כדי לגשת למצלמה שלך כדי לצלם תמונות ושיחות וידאו. + אלמנט זקוק להרשאה כדי לגשת לספריית התמונות והווידיאו שלך כדי לשלוח ולשמור קבצים מצורפים. +\n +\nאנא אפשר גישה בחלון הקופץ הבא כדי שתוכל לשלוח קבצים מהטלפון שלך. + מידע + לא ניתן להקליט וידאו + צלם תמונה או סרטון + השיחה נענתה במקום אחר + לא ניתן לאתחל את המצלמה + חיבור המדיה נכשל + הצד המרוחק לא הצליח להרים. + חזור לשיחה + שיחה פעילה (%s) + שיחת וידאו מתבצעת … + במהלך התקשרות… + שיחה קולית נכנסת + שיחת וידאו נכנסת + שיחה נכנסת + מתקשר… + שיחה הסתיימה + שיחה מתחברת … + שיחה מחוברת + שִׂיחָה + בחר רינגטון לשיחות: + רינגטון שיחה נכנסת + ישתמש ב-%s כסיוע כאשר השרת הביתי שלך אינו מציע כזה (כתובת ה- IP שלך תשותף במהלך שיחה) + אפשר שרת עזרה לשיחות + השתמש ברינגטון ברירת המחדל של אלמנט לשיחות נכנסות + בקש אישור לפני שמתחילים בשיחה + מנע שיחה מקרית + שיחות + נושא החדר + שם חדר + היום + אתמול + %1$dm %2$ds + % d s + האם לבטל את ההעלאה\? + האם לבטל את ההורדה\? + קטן + בינוני + גדול + מקור + שלח כ + + שינוי בפרט חברות + שינוי בפרטי חברות + שינוי בפרטי חברות + שינוי בפרטי חברות + + רשימת קבוצות + קרא את רשימת הקבלות + הפעל את Element במכשיר אחר שיכול לפענח את ההודעה כדי שיוכל לשלוח את המפתחות להפעלה זו. + הבקשה נשלחה + בקשת המפתח נשלחה. + בקש מחדש מפתחות הצפנה מהפעלות האחרות שלך. + בטל הכל + שלח מחדש הכל + הודעות לא נשלחו בגלל הימצאות פעילויות לא ידועות. %1$s או %2$s עכשיו\? + הודעות לא נשלחו. %1$s או %2$s עכשיו\? + הקישוריות לשרת אבדה. + שלח תשובה (לא מוצפן) … + יעדי התראות + ניהול מפתחות קריפטוגרפיה + קריפטוגרפיה + השתמש במנהל שילוב לניהול בוטים, גשרים, ווידג\'טים וחבילות מדבקות. +\nמנהלי אינטגרציה מקבלים נתוני תצורה ויכולים לשנות ווידג\'טים, לשלוח הזמנות לחדר ולהגדיר רמות כוח מטעמכם. + אינטגרציות + מתקדם + אחר + משתמשים שמתעלמים מהם + התראות + הגדרות משתמש + נקה מטמון מדיה + נקה את זיכרון המטמון + שמור על מדיה + מדיניות הפרטיות + זכויות יוצרים + התראות צד שלישי + תנאים והגבלות + גרסת olm + גִרְסָה + + % d שנייה + % d שניות + % d שניות + % d שניות + + עיכוב בין כל סינכרון + %s +\nהסנכרון עשוי להידחות בהתאם למשאבים (סוללה) או מצב ההתקן (שינה). + מרווח סינכרון מועדף + פסק-זמן לבקשה לסנכרון + אפשר סנכרון רקע + החל באתחול + עדכון ההגדרות נכשל. + לא תקבל הודעה על הודעות נכנסות כאשר האפליקציה ברקע. + אין סנכרון רקע + אלמנט יסונכרן ברקע מעת לעת בזמן מדויק (ניתן להגדרה). +\nזה ישפיע על השימוש ברדיו ובסוללה, תוצג הודעה קבועה לפיה אלמנט מאזין לאירועים. + מותאם לזמן אמת + אלמנט יסונכרן ברקע באופן שישמור על המשאבים המוגבלים של המכשיר (סוללה). +\nבהתאם למצב משאבי המכשיר שלך, ייתכן שהסנכרון יידחה על ידי מערכת ההפעלה. + מותאם לסוללה + מצב סנכרון רקע + סנכרון רקע + הודעות שנשלחו על ידי בוט + הזמנות לשיחות + כשאני מוזמן לחדר + הודעות בצ\'אטים קבוצתיים + הודעות בצ\'אטים אחד-על-אחד + הודעות שמכילות את שם המשתמש שלי + הודעות שמכילות את שם התצוגה שלי + בחר צבע LED, רטט, צליל … + הגדר התראות שקטות + הגדר התראות על שיחות + הגדר תצורה של התראות רועשות + הדלק את המסך למשך 3 שניות + אפשר התראות עבור מושב זה + אפשר התראות עבור חשבון זה + צליל התראה + • התראות <b> לא יציגו את תוכן ההודעה </ b>not show message content + • התראות מכילות <b> נתוני ליבה והודעות </ b>meta and message data + • תוכן ההודעה של ההודעה <b> ממוקם בצורה מאובטחת ישירות משרת הבית של מטריקס </ b>located securely direct from the Matrix homeserver + • התראות מכילות רק נתוני ליבה + • התראות נשלחות באמצעות Firebase Cloud Messaging + היישומים <b> לא </ b> צריכים להתחבר ל- HomeServer ברקע, זה אמור להפחית את השימוש בסוללהnot need to connect to the HomeServer in the background, it should reduce battery usage + האפליקציה זקוקה לאישורך כדי לפעול ברקע + פרטיות מצומצמת + רגיל + התעלם מאופטימיזציה + אם משתמש משאיר מכשיר מחובר לחשמל ויציב לתקופה מסוימת, כשהמסך כבוי, המכשיר עובר למצב Doze. זה מונע מאפליקציות גישה לרשת ומגדיר את העבודות, הסנכרונים וההתראות הסטנדרטיות שלהם. + אלמנט אינו מושפע מתהליך מיטוב הסוללה. + אופטימיזציה של הסוללה + השבת הגבלות + מגבלות רקע מופעלות עבור Element. +\nהעבודה שהאפליקציה מנסה לעשות תוגבל באגרסיביות בזמן שהיא ברקע, וזה עלול להשפיע על ההודעות. +\n%1$s + מגבלות רקע מושבתות עבור Element. יש להריץ בדיקה זו באמצעות נתונים ניידים (ללא WIFI). +\n%1$s + בדוק מגבלות רקע + הפעל את התחלה לאחר אתחול + השירות לא יופעל עם הפעלת המכשיר מחדש, לא תקבל התראות עד שאלמנט ייפתח לפחות פעם אחת. + השירות יתחיל עם הפעלת המכשיר מחדש. + הפעל לאחר אתחול + השירות נכשל מלעלות מחדש + השירות נסגר והופעל מחדש אוטומטית. + הפעלה מחדש אוטומטית לשירות ההתראות + החל שירות + שירות ההתראות אינו פועל. +\nנסה להפעיל מחדש את היישום. + שירות ההתראות פועל. + שירות התראות + ההודעה נלחצה! + אנא לחץ על ההודעה. אם אינך רואה את ההודעה, אנא בדוק את הגדרות המערכת. + תצוגת התראות + אתה צופה בהודעה! לחץ עלי! + קבלת הדחיפה נכשלה. הפתרון יכול להיות התקנה מחדש של היישום. + בדיקת שליחה בדחיפה (PUSH) + היישום מקבל PUSH + היישום ממתין ל- PUSH + נכשל רישום אסימון FCM ל- HomeServer: +\n%1$s + אסימון FCM נרשם בהצלחה ל- HomeServer. + רישום אסימונים + הוסף חשבון + [%1$s] +\nשגיאה זו אינה בשליטה על אלמנט. אין חשבון Google בטלפון. אנא פתח את מנהל החשבון והוסף חשבון Google. + [%1$s] +\nשגיאה זו אינה בשליטה על אלמנט. זה יכול להתרחש מכמה סיבות. אולי זה יעבוד אם תנסה שוב מאוחר יותר, תוכל גם לבדוק ששירות Google Play אינו מוגבל בשימוש נתונים בהגדרות המערכת, או ששעון המכשיר שלך תקין, או שזה יכול לקרות ב- ROM מותאם אישית. + [%1$s] +\nשגיאה זו איננה בשליטה על Element ולפי גוגל, שגיאה זו מצביעה על כך שלמכשיר יש יותר מדי אפליקציות הרשומות ב- FCM. השגיאה מתרחשת רק במקרים שבהם ישנם מספרים קיצוניים של אפליקציות, כך שהיא לא אמורה להשפיע על המשתמש הממוצע. + נכשל באחזור אסימון FCM: +\n%1$s + אסימון FCM אוחזר בהצלחה: +\n%1$s + אסימון Firebase + תקן שירותי Google Play + אלמנט משתמש בשירותי Google Play כדי להעביר הודעות פוש אך נראה שהוא אינו מוגדר כהלכה: +\n%1$s + ה- APK של שירותי Google Play זמין ומעודכן. + בדיקת שירותי הפעלה + בדוק בהגדרות + טעינת הכללים המותאמים אישית נכשלה, אנא נסה שוב. + חדרים + אין תוצאות + סנן משתמשים מודרים + סנן חברים מהחדר + חפש + בטל הורדה + בטל העלאה + האם ברצונך להסתיר את כל ההודעות ממשתמש זה\? +\nשים לב שפעולה זו תפעיל מחדש את האפליקציה והיא עשויה להימשך זמן מה. + סיבה לדיווח על תוכן זה + הצטרף + מוזמן + תעודת זהות שגויה. צריכה להיות כתובת דוא\"ל או מזהה מטריצה כמו \'@localpart: domain\' + + % d נבחר + % d נבחרים + % d נבחרים + % d נבחרים + + הגדרות + קבצים + אנשים + פרטי החדר + קבל את האישור רק אם מנהל השרת פרסם טביעת אצבע התואמת את זו שלמעלה. + האישור השתנה מאישור מהימן בעבר לאיש מהימן. ייתכן שהשרת חידש את האישור שלו. פנה למנהל השרת לקבלת טביעת האצבע הצפויה. + האישור השתנה מאישור שהטלפון שלך אמין עליו. זה מאוד לא שגרתי. מומלץ לא לקבל את האישור החדש הזה. + אם מנהל השרת אמר שזה צפוי, ודא שטביעת האצבע שלמטה תואמת את טביעת האצבע שמספקת אותם. + יכול להיות שמישהו מיירט את התעבורה שלך בזדון, או שהטלפון שלך לא סומך על האישור שמספק השרת המרוחק. + לא ניתן לאמת את זהות השרת המרוחק. + טביעת אצבע (%s): + התעלם + יציאה + אל תתן אמון + אמון + + הודעה חדשה + הודעות חדשות + הודעות חדשות + הודעות חדשות + + אין לך הרשאה לפרסם בחדר זה + הקובץ לא נמצא + מחק הודעות שלא נשלחו + שלח שוב הודעות שלא נשלחו + שלח תשובה מוצפנת … + שלח הודעה (לא מוצפן) … + שלח הודעה מוצפנת … + %1$s &%2$s ואחרים מקלידים … + %1$s &%2$s מקלידים … + %s מקליד … + חפש + אימייל או מזהה מטריקס + אנא הזן כתובת דוא\"ל אחת או יותר או מזהה מטריקס + הזמן משתמש לפי מזהה + משתמשי מטריקס בלבד + אנשי קשר מקומיים (%d) + <u> הזמן לפי מזהה </ u>Invite by ID + %1$s %2$s + %1$s and %2$s + "%1$s, " + האם אתה בטוח שברצונך להזמין את%s לצ\'אט זה\? + סיבה + הסרת נידוי ממשתמש יאפשר לו להצטרף שוב לחדר. + איסור על המשתמש יבעט בהם מחדר זה וימנע מהם להצטרף שוב. + הסר נידוי ממשתמש + סיבות לנידוי + נדה משתמש + משתמש מעיף יסיר אותם מחדר זה. +\n +\nכדי למנוע מהם להצטרף שוב, עליך לאסור אותם במקום זאת. + סיבות להעפה + העף משתמש + האם אתה בטוח שברצונך לבטל את ההזמנה עבור משתמש זה\? + בטל הזמנה + הסרת התעלמות + ביטול חתימת משתמש זה יציג את כל ההודעות מהם שוב. + הסרת התעלמות ממשתמש + התעלם + התעלמות ממשתמש זה תסיר את ההודעות שלו מחדרים שאתה משתף. +\n +\nאתה יכול להפוך פעולה זו בכל עת בהגדרות הכלליות. + התעלם ממשתמש + לְהוֹרִיד בְּדַרגָה + לא תוכל לבטל את השינוי הזה מכיוון שאתה מוריד את עצמך בדרגה, אם אתה המשתמש המיועד האחרון בחדר, אי אפשר יהיה להחזיר לו הרשאות. + להוריד את עצמך\? + לא תוכל לבטל את השינוי הזה מכיוון שאתה מקדם את המשתמש לאותה רמת כוח כמוך. +\nהאם אתה בטוח\? + הצג רשימת מושבים + אזכר + מזהה משתמש, שם או דוא\"ל + הפוך למנהל + הפוך למנחה + אפס למשתמש רגיל + העף + הסרת התעלמות + התעלם + הסר מחדר זה + עזוב חדר זה + בטל הזמנה + הזמן + מושבים + הודעות ישירות + שיחה + כלי אדמיניסטרציה + זמין + אופליין + אונליין + צור + חלק מההתראות מושבתות בהגדרות המותאמות אישית שלך. + שים לב שחלק מסוגי ההודעות מוגדרים כשתיקים (יפיקו התראה ללא צליל). + הגדרות מותאמות אישית. + אפשר + התראות אינן מופעלות עבור הפעלה זו. +\nאנא בדוק את הגדרות האלמנט. + התראות מופעלות להפעלה זו. + הגדרות מושב. + אפשר + התראות מושבתות עבור חשבונך. +\nאנא בדוק את הגדרות החשבון. + התראות מופעלות עבור חשבונך. + הגדרות חשבון. + פתח את ההגדרות + התראות מושבתות בהגדרות המערכת. +\nאנא בדוק את הגדרות המערכת. + התראות מופעלות בהגדרות המערכת. + הגדרות מערכת. + בדיקה אחת או יותר נכשלו, אנא שלח דו\"ח שגיאה שיעזור לנו לחקור זאת. + בדיקה אחת או יותר נכשלו, נסה הצעה/ות אלו לתיקון. + אבחון בסיסי תקין. אם עדיין אינך מקבל התראות, אנא שלח דו\"ח שגיאה שיעזור לנו לחקור זאת. + הרץ מבדקים + אבחון לפתרון בעיות + פותר בעיות התראות + פרטיות הודעות + חשיבות ההודעה לפי אירוע + הגדרות התראה מתקדמות + וודא שלחצת על הקישור בהודעת הדוא\"ל ששלחנו אליך. + להסיר את%s\? + מספרי טלפון + לא הוספה כתובת דוא\"ל לחשבונך + כתובות דוא\"ל + נדרש אימות + אינך יכול לעשות זאת ממכשיר נייד + אשר את סיסמתך + הצג את פרטי היישום בהגדרות המערכת. + מידע על האפליקציה + הוסף מספר טלפון + לא הוסף מספר טלפון לחשבונך + מספר טלפון + הוסף כתובת דוא\"ל + כתובת דוא\"ל + שם תצוגה + תמונת פרופיל + מדיניות הפרטיות + זכויות יוצרים + התראות צד שלישי + תנאים והגבלות + גרסה + הגדרות + הודעות + הוסף למסך הבית + שכח + עזוב את השיחה + צ\'אט ישיר + בטל עדיפות + מועדף + השתק + אזכורים בלבד + כל ההודעות + כל ההודעות (קוליות) + מחפש בתיקייה… + + d% חדר + d% חדרים + d% חדרים + d% חדרים + + חפש בתיקיות + הקלד מזהה חדר או כינוי לחדר + הצטרף לחדר + הצטרף לחדר + צור חדר + התחלת שיחת צ\'אט + הזמנות + עדיפות נמוכה + חדרים + מועדפים + תיקייה ראשית + הצטרף + עדיין אין תמיכה בחיפוש בחדרים מוצפנים. + קבצים + אנשים + הודעות + האם אתה בטוח שברצונך להסיר את%s מהצ\'אט הזה\? + האם ברצונך לעזוב את החדר\? + עזוב חדר + + %dd + %dd + %dd + %dd + + + %dh + %dh + %dh + %dh + + + %dm + %dm + %dm + %dm + + + %ds + %ds + %ds + %ds + + חבר אחד + + חבר + חברים + חברים + חברים + + + חבר פעיל + חברים פעילים + חברים פעילים + חברים פעילים + + הוסף חבר + התחל אימות + מושב לא מאומת מבקש מפתחות הצפנה. +\nשם מושב: %1$s +\nנראה לאחרונה: %2$s +\nאם לא נכנסת למפגש אחר, התעלם מבקשה זו. + ההפעלה \'%s\' לא מאומתת מבקשת מפתחות הצפנה. + מושב חדש מבקש מפתחות הצפנה. +\nשם מושב: %1$s +\nנראה לאחרונה: %2$s +\nאם לא נכנסת למפגש אחר, התעלם מבקשה זו. + הוספת מושב חדש \'%s\', המבקש מפתחות הצפנה. + כדי להמשיך עליך לקבל את תנאי השירות הזה. + אפשרות זו מחייבת יישום צד שלישי להקליט את ההודעות. + שלח הודעות קוליות + השתמש במקש הזנת המקלדת כדי לשלוח הודעה + הפעל את מצלמת המערכת במקום את מסך המצלמה המותאם אישית. + השתמש במצלמה מקומית + אין יישומונים פעילים + נהל אינטגרציות + הוסף אפליקציות מטריקס + לא הוגדר מנהל אינטגרציה. + פרמטר אינו חוקי. + פרמטר חובה חסר. + החדר %s אינו גלוי. + חסר זהות משתמש בבקשה. + חסר מספר זהות חדר בבקשה. + אין לך אישור לעשות זאת בחדר זה. + אתה לא בחדר הזה. + רמת הרשאה חייבת להיות חיובית שלמה. + שליחת הבקשה נכשלה. + לא ניתן ליצור יישומון. + קרא מדיה מוגנת DRM + השתמש במיקרופון + השתמש במצלמה + חסום הכל + אפשר + יישומון זה רוצה להשתמש במשאבים הבאים: + מצטערים, שיחות ועידה עם Jitsi אינן נתמכות במכשירים ישנים (מכשירים עם מערכת הפעלה אנדרואיד מתחת ל -5.0) + מזהה חדר + מזהה ישומון + ערכת הנושא שלכם + מזהה המשתמש שלך + כתובת האתר של הדמות שלך + שם התצוגה שלך + בטל גישה עבורי + פתח בדפדפן + טען יישומון מחדש + השימוש בו עשוי לשתף נתונים עם %s: + השימוש בו עשוי להגדיר קובצי cookie ולשתף נתונים עם %s: + ישומון זה התווסף על ידי: + טען ישומון + ישומון + ישומונים פעילים + צפה + + %d יישומון פעיל + %d ישומונים פעילים + %d ישומונים פעילים + %d ישומונים אחרים פעילים + + האם אתה בטוח שברצונך למחוק את היישומון מחדר זה\? + צור שיחות ועידה עם jitsi + יצירת היישומון נכשלה + אתה זקוק להרשאה כדי לנהל יישומונים בחדר זה + ענק + הכי גדול + גדול יותר + גדול + רגיל + קטן + זעיר + גודל גופן + חפש היסטורי + %1$s: %2$s %3$s + %1$s:%2$s + ** השליחה נכשלה - אנא פתח את החדר + אני + הזמנות חדשות + הודעות חדשות + חדר + מאורע חדש + %1$s ו %2$s + %1$s ב %2$s ו %3$s + %1$s ב %2$s + + התראה %1$s: %2$d + התראות %1$s: %2$d + התראות מועטות %1$s: %2$d + התראות אחרות %1$s: %2$d + + + הודעה %1$s: %2$d + הודעות %1$s: %2$d + הודעות מעטות %1$s: %2$d + הודעות אחרות %1$s: %2$d + + + %d הזמנה + %d הזמנות + %d הזמנות מעטות + %d הזמנות אחרות + + + %d חדר + %d חדרים + %d חדרים מועטים + %d חדרים אחרים + + + %d הודעת התראה שלא נקראה + %d הודעות התראה שלא נקראו + %d הודעות התראה מעטות שלא נקראו + %d הודעות התראה אחרות שלא נקראו + + + הודעת התראה %d שלא נקראה + %d הודעות התראה שלא נקראו + %d הודעות התראה מעטות שלא נקראו + %d הודעות התראה אחרות שלא נקראו + + הקלד פה… + כל החדרים המקומיים %s + כל החדרים בשרת %s + כתובת אתר של שרת בית + הקלד שרת בית כדי לרשום ממנו חדרים ציבוריים + ייתכן שהשרת אינו זמין או עומס יתר + בחר מדריך חדרים + חדר זה מכיל פעילויות לא ידועות שלא אומתו. +\nהמשמעות היא שאין ערובה לכך שההפעלות שייכות למשתמשים שהם טוענים להם. +\nאנו ממליצים שתעבור את תהליך האימות של כל מפגש לפני שתמשיך, אך תוכל לשלוח שוב את ההודעה מבלי לאמת אם אתה מעדיף. +\n +\nהפעלות לא ידועות: + החדר מכיל הפעלות לא ידועות + אני מאשר שהמפתחות תואמים + אם הם לא תואמים, אבטחת התקשורת שלך עלולה להיפגע. + אשרו על ידי השוואה בין הדברים הבאים להגדרות המשתמש בפגישה האחרת שלכם: + אמת מושב + הסר מרשימה שחורה + רשימה שחורה + הסר אימות + אמת + ללא + IP לא ידוע + מושב לא ידוע + ברשימה שחורה + מאומת + לא תקין + + מפתח %1$d/%2$d מיובא בהצלחה. + מפתחות %1$d/%2$d יובאו בהצלחה. + מפתחות %1$d/%2$d מעטים יובאו בהצלחה. + מפתחות %1$d/%2$d אחרים יובאו בהצלחה. + + לעולם אל תשלח הודעות מוצפנות להפעלות לא מאומתות מהפגישה זו. + הצפן למפגשים מאומתים בלבד + יבא + ייבא את המפתחות מקובץ מקומי + ייבא מפתחות לחדר + ייבא מפתחות לחדר E2E + נהל גיבוי מפתח + שחזור הודעות מוצפנות + מפתחות יוצאו בהצלחה + מקשי החדר E2E נשמרו ב- \'%s\'. +\n +\nאזהרה: קובץ זה עשוי להימחק אם הסרת ההתקנה של היישום. + אנא צור משפט סיסמה להצפנת המפתחות המיוצאים. יהיה עליך להזין את אותו ביטוי סיסמה כדי שתוכל לייבא את המפתחות. + יצא + יצא מפתחות לקובץ מקומי + יצא מפתחות חדר + ייצא מפתחות חדר E2E + טביעת אצבע Ed25519 + אימות + מזהה מפתח + מזהה מושב + שם ציבורי + השם הציבורי של הפגישה גלוי לאנשים שאיתם אתה מתקשר + שם ציבורי (גלוי לאנשים שאיתם אתה מתקשר) + שם ציבורי + מידע על מושב השולח + שגיאת פענוח + מזהה מושב + מזהה משתמש + אַלגוֹרִיתְם + תביעת מפתח טביעת אצבע של Ed25519 + מפתח זהות Curve25519 + מידע על האירוע + מידע על הצפנה מקצה לקצה + %s ניסתה לטעון נקודה מסוימת בציר הזמן של החדר הזה אך לא הצליחה למצוא אותה. + ערכת נושא + מַדרִיך + אפשר הצפנה +\n(אזהרה: לא ניתן להשבית שוב!) + הצפנה מושבתת בחדר זה. + הצפנה מופעלת בחדר זה. + העתק כתובת חדר + העתק מזהה חדר + ביטול ההגדרה ככתובת הראשית + הגדר ככתובת ראשית + אזהרות כתובת עיקריות + לא תהיה לך כתובת ראשית שצוינה לחדר זה. + \'%s\' אינו פורמט חוקי לכינוי + פורמט כינוי לא חוקי + \'%s\' אינו מזהה קהילה חוקי + מזהה קהילה לא חוקי + מזהה קהילה חדש (למשל + foo: matrix.org) + חדר זה אינו מגלה כישרון בקרב קהילות כלשהן + כתובת חדשה (למשל #foo: matrix.org) + לחדר זה אין כתובות מקומיות + לעולם אל תשלח הודעות מוצפנות להפעלות לא מאומתות בחדר זה מהפגישה זו. + הצפן לביקורים מאומתים בלבד + עליך להתנתק כדי שתוכל לאפשר את ההצפנה. + הצפנה מקצה לקצה פעילה + הצפנה מקצה לקצה + אלה תכונות ניסיוניות שעשויות להישבר בדרכים לא צפויות. השתמש בזהירות. + מעבדות + כתובות + תעודת הזהות הפנימית של החדר הזה + מתקדם + משתמשים אסורים + כל מי שמכיר את הקישור לחדר, כולל אורחים + כל מי שמכיר את הקישור לחדר, מלבד האורחים + רק אנשים שהוזמנו + כדי לקשר לחדר חייבת להיות כתובת. + חברים בלבד (מאז שהצטרפו) + חברים בלבד (מאז שהוזמנו) + חברים בלבד (מאז נקודת הזמן לבחירת אפשרות זו) + כל אדם + לא ניתן לאחזר את הראות הנוכחית של ספריית החדרים (%1$s). + לפרסם את החדר הזה לציבור במדריך החדרים של %1$s\? + בטל את הפרסום של כתובת זו + פרסם כתובת זו + הוסף כתובת מקומית + לחדר זה אין כתובות מקומיות + הגדר כתובות לחדר זה כדי שמשתמשים יוכלו למצוא את החדר הזה דרך שרת הבית שלך (%1$s) + כתובות מקומיות + כתובת שפורסמה חדשה (למשל alias:server#) + עדיין אין כתובות שפורסמו. + עדיין אין כתובות שפורסמו, הוסף כתובת למטה. + פרסם חדר זה כציבורי ברשימת החדרים של \"%1$s\"\? + מחק את הכתובת \"%1$s\"\? + הסר פרסום של הכתובת \"%1$s\"\? + פרסם + פרסם כתובת חדשה באופן ידני + כתובות אחרות שפורסמו: + כתובת ראשית + זו הכתובת העיקרית + כל אחד מכל שרת יכול להשתמש בכתובות שפורסמו כדי להצטרף לחדר שלך. כדי לפרסם כתובת, תחילה יש להגדיר אותה ככתובת מקומית. + כתובות שפורסמו + כתובות חדרים + ראה וניהול כתובות של חדר זה, והנראות שלו בספריית החדרים. + כתובות החדר + גישה לחדר + מי יכול לגשת לחדר הזה\? + שינויים במי שיכול לקרוא היסטוריה יחולו רק על הודעות עתידיות בחדר זה. נראות ההיסטוריה הקיימת לא תשתנה. + מי יכול לקרוא היסטוריה\? + הקריאה בהיסטוריה של החדרים + גישה לחדר + התראות + רשום חדר זה ברשימת החדרים + כניסה ונראות + ללא + עדיפות נמוכה + מועדפים + תוייג כ-: + תגית חדר + נושא + שם חדר + תמונת חדר + לעד + חודש 1 + שבוע 1 + 3 ימים + אינכם חברים בשום קהילה. + כשרון + השמע צליל תריס + בחרו + מקור מדיה ברירת מחדל + בחרו + דחיסת ברירת מחדל + מדיה + מידע נוסף: %s + אירעה שגיאה במהלך אימות מספר הטלפון שלך. + קוד + שגיאה בעת אימות מספר הטלפון שלך + הזן קוד הפעלה + שלחנו SMS עם קוד הפעלה. אנא הזן קוד זה למטה. + אימות טלפון + מספר טלפון לא חוקי עבור המדינה שנבחרה + מספר טלפון + בבקשה בחרו מדינה + מדינה + בחר\\י מדינה + האם אתה בטוח שברצונך להסיר את %1$s %2$s \? + האם אתה בטוח שברצונך להסיר את יעד ההודעות הזה\? + נהל מיילים ומספרי טלפון המקושרים לחשבון מטריקס שלך + דוא\"ל ומספר טלפון + סיסמאות לא תואמות + הצג את כל ההודעות מ- %s\? +\n +\nשים לב שפעולה זו תפעיל מחדש את האפליקציה והיא עשויה להימשך זמן מה. + הסיסמה שלכם עודכנה + הסיסמה אינה תקינה + עדכון הסיסמה נכשל + עדכון סיסמה + אישור סיסמה חדשה + סיסמה חדשה + סיסמה נוכחית + שינוי סיסמה + סיסמה + הסתיים + שמור על מפתח התאוששות שלך במקום כלשהו מאובטח מאוד, כמו מנהל סיסמאות (או כספת) + מפתח השחזור שלך הוא רשת ביטחון - אתה יכול להשתמש בו כדי להחזיר את הגישה להודעות המוצפנות שלך אם תשכח את משפט הסיסמה שלך. +\nשמור על מפתח התאוששות שלך במקום כלשהו מאובטח מאוד, כמו מנהל סיסמאות (או כספת) + המפתחות שלך מגובים. + הצלחה! + (מתקדם) הגדר עם מפתח השחזור + לחלופין, אבטח את הגיבוי שלך באמצעות מפתח שחזור ושמור אותו במקום בטוח. + יוצר גיבוי + הגדר ביטוי + אנו נאחסן עותק מוצפן של המפתחות שלך בשרת הבית שלך. הגן על הגיבוי שלך באמצעות משפט סיסמה כדי לשמור על אבטחתו. +\n +\nליתר ביטחון, זה צריך להיות שונה מסיסמת החשבון שלך. + אבטח את הגיבוי שלך באמצעות משפט סיסמה. + ייצא ידנית מפתחות + (מתקדם) + התחל להשתמש בגיבוי מקשים + הודעות בחדרים מוצפנים מאובטחות באמצעות הצפנה מקצה לקצה. רק אתה והנמען / ים יש את המקשים לקריאת ההודעות האלה. +\n +\nגבה את המפתחות שלך בצורה מאובטחת כדי לא לאבד אותם. + לעולם אל תאבד הודעות מוצפנות + אין מושב מטריקס זמין + אנא מחק את משפט הסיסמה אם ברצונך ש- Element ייצור מפתח שחזור. + משפט הסיסמה חלש מדי + אנא הזן משפט סיסמה + משפט הסיסמה אינו תואם + הזן ביטוי סיסמה + אשר את ביטוי הסיסמה + צור ביטוי סיסמה + לא נמצא APK חוקי של שירותי Google Play. ייתכן שההודעות לא יפעלו כראוי. + %d+ + +%d + %1$s: %2$s + %1$s: + רק עבור שגיאות + עבור הודעות ושגיאות + לעולם + הראה את אזור המידע + כווץ + הרחב + סליחה, שגיאה התרחשה + שרת הבית שלך עדיין לא תומך בטעינה עצלה של חברי החדר. נסה מאוחר יותר. + הגדל את הביצועים רק על ידי חברי חדר העמסה בתצוגה הראשונה. + טעינה עצלה של חברים וחדרים + אנא %s להמשיך להשתמש בשירות זה. + אנא %s כדי להגדיל מגבלה זו. + שרת בית זה הגיע למגבלת המשתמשים הפעילים החודשיים שלו. + שרת בית זה הגיע למגבלת המשתמשים הפעילים החודשיים כך ש חלק מהמשתמשים לא יוכלו להתחבר . + שרת בית זה חרג מאחד ממגבלות המשאבים שלו. + שרת בית זה חרג מאחד ממגבלות המשאבים שלו כך ש משתמשים מסוימים לא יוכלו להתחבר . + פנה למנהל השירות שלך + צור קשר עם מנהל המערכת + לחץ כאן כדי לראות הודעות ישנות יותר ממגבלת המשאבים + לחץ כאן לצפייה בהודעות ישנות יותר + החדר הזה הוא המשך לשיחה אחרת + השיחה נמשכת כאן + חדר זה הוחלף ואינו פעיל יותר + אנא הזינו את סיסמה שלכם. + אהא הזינו שם משתמש. + השבת חשבון + להמשך, הזן את הסיסמה שלך: + אנא שכח את כל ההודעות ששלחתי כאשר חשבוני מושבת (אזהרה: הדבר יגרום למשתמשים עתידיים לראות תצוגה חלקית של השיחות) + זה יהפוך את חשבונך ללא שימוש לצמיתות. לא תוכל להתחבר, ואף אחד לא יוכל לרשום מחדש את אותו מזהה משתמש. הדבר יביא לחשבונך לעזוב את כל החדרים בהם הוא משתתף, והוא יסיר את פרטי חשבונך משרת הזהות שלך. פעולה זו היא בלתי הפיכה . +\n +\nהשבתת חשבונך אינה גורמת לנו כברירת מחדל לשכוח הודעות ששלחת . אם תרצה שנשכח את ההודעות שלך, סמן את התיבה למטה. +\n +\nנראות ההודעות במטריקס דומה לדוא\"ל. המשמעות של שכחת ההודעות שלך היא שהודעות ששלחת לא ישותפו עם משתמשים חדשים או לא רשומים, אך למשתמשים רשומים שכבר יש גישה להודעות אלה עדיין תהיה גישה להעתק שלהם. + השבת חשבון + בדוק כעת + כדי להמשיך להשתמש בשרת הבית %1$s עליך לבדוק ולהסכים לתנאים ולהגבלות. + אווטאר + אוואטר התרעה + אווטאר קבלה + שכח חדר + לָשׁוּב וֵלְהִצְטַרֵף + סיבה: %1$s + חסום על ידי %2$s מ- %1$s + אתה נבעט מ- %1$s על ידי %2$s + מנהל הקהילה לא סיפק תיאור ארוך לקהילה זו. + + חדר %d + %d חדרים + %d חדרים + %d חדרים אחרים + + + חבר %d + %d חברים + %d חברים + %d חברים אחרים + + סנן קבוצות חדרים + סנן חברי קבוצה + הוזמנו + הצתרפו + חדרים + אין משתמשים + חדרים + אנשים + בית + דוגמא + מזהה קהילה + דוגמא + שם הקהילה + צור קהילה + צור + הודעה מוצפנת + רועש + שקט + כבוי + סימון ההפעלה הושבת. + סימון ההפעלה הופעל. + כדי לתקן את ניהול אפליקציות מטריקס + הפעלה / כיבוי של סימון MARKDOWN + משנה את כינוי התצוגה שלך + בועט משתמש עם מזהה נתון + הגדר את נושא החדר + עזוב חדר + מצטרף לחדר עם כינוי נתון + מזמין משתמש עם זיהוי נתון לחדר הנוכחי + משתמש מבוטל עם מזהה נתון + הגדר את רמת ההרשאה של המשתמש + הסר חסימה למשתמש עם מזהה נתון + חסום משתמש עם מזהה נתון + הצג פעולה + הפקודה \"%s\" זקוקה ליותר פרמטרים, או שחלק מהפרמטרים שגויים. + פקודה לא מוכרת: %s + שגיאת פקודה + שיחת ועידה נמצאת בפיתוח ואולי לא אמינה. + אזהרה! + התעלם + התעלם מהבקשה + בקשה לשיתוף מפתח + שיתוף + שתף ללא אימות + אמת + כפתור Enter על המקלדת הרכה ישלח הודעה במקום להוסיף מעבר שורה + שלח הודעה עם Enter + הצג תצוגה מקדימה של מדיה לפני השליחה + רטוט בעת אזכור משתמש + כולל שינויים באווטאר ושמות תצוגה. + הצג אירועי חשבון + הזמנות, בעיטות ואיסורים אינם מושפעים. + הראה אירועי הצטרפות ועזיבה + כולל אירועי הזמנה / הצטרפות / שמאל / בעיטה / איסור ושינוי שם אווטאר / תצוגה. + הצג אירועים של מדינת החברים בחדר + לחץ על אישורי הקריאה לרשימה מפורטת. + הצג קבלות הצג קבלות קריאה + הצג חותמות זמן בפורמט של 12 שעות + הצג חותמות זמן לכל ההודעות + עצב הודעות באמצעות תחביר הסימון לפני שהן נשלחות. זה מאפשר עיצוב מתקדם כגון שימוש בכוכביות להצגת טקסט נטוי. + עיצוב Markdown + הודע למשתמשים אחרים שאתה מקליד. + שלח הודעות הקלדה + תצוגה מקדימה של קישורים בצ\'אט כאשר שרת הבית שלך תומך בתכונה זו. + תצוגה מקדימה של כתובת אתר מוטמעת + מושבים + הצמד חדרים עם הודעות שלא נקראו + הצמד חדרים עם התראות שלא נענו + ארץ ספר הטלפונים + מסך ראשי + הרשאת אנשי קשר + אנשי קשר מקומיים + לעולם אל תאבד הודעות מוצפנות + להגן מפני אובדן גישה להודעות ונתונים מוצפנים + גיבוי מאובטח + התחל להשתמש בגיבוי מפתח + לעולם אל תאבד הודעות מוצפנות + זה היה אני + גיבוי מפתח חדש גיבוי חדש של מפתח הודעות מאובטח. +\n +\nאם לא הגדרת את שיטת השחזור החדשה, ייתכן שתוקף מנסה לגשת לחשבונך. שנה את סיסמת החשבון שלך והגדר מיד שיטת שחזור חדשה בהגדרות. + גיבוי מפתח חדש + מחק גיבוי למחוק את מפתחות ההצפנה המגובים שלך מהשרת\? לא תוכל עוד להשתמש במפתח השחזור שלך כדי לקרוא את היסטוריית ההודעות המוצפנת. + מחק את הגיבוי + בודק מצב גיבוי + מחיקת הגיבוי נכשלה (%s) + מוחק גיבוי … + כדי להשתמש בגיבוי מקשים בהפעלה זו, שחזר באמצעות משפט הסיסמה או מפתח השחזור שלך כעת. + נכשל קבלת פרטי אמון לגיבוי (%s). + לגיבוי יש חתימה לא חוקית מהפעלה %s לא מאומתת + לגיבוי יש חתימה לא חוקית מההפעלה %s המאומתת + לגיבוי יש חתימה חוקית מהפעלה %s לא מאומתת + לגיבוי יש חתימה מהפעלה לא ידועה עם מזהה %s. + לגיבוי יש חתימה חוקית מההפעלה המאומתת %s. + לגיבוי יש חתימה חוקית מהפגישה זו. + לא מגובים את המפתחות שלך מהפגישה זו. + גיבוי המפתח אינו פעיל בהפעלה זו. + גיבוי המפתח הוגדר כהלכה להפעלה זו. + מחק את הגיבוי + שחזר מגיבוי + הצפנת מושב אינה מופעלת + השגת הגרסה האחרונה של מפתחות השחזור (%s) נכשלה. + הגיבוי שוחזר %s! + לא ניתן היה לפענח את הגיבוי באמצעות מפתח שחזור זה: ודא שהזנת את מפתח השחזור הנכון. + אנא הכנס מפתח שחזור + בטל נעילת היסטוריה + מייבא מפתחות … + מוריד מקשים … + מפתח שחזור מחשוב … + שחזור הגיבוי: + שגיאת רשת: אנא בדוק את החיבור שלך ונסה שוב. + לא ניתן לפענח גיבוי באמצעות ביטוי סיסמה זה: אנא ודא שהזנת את ביטוי הסיסמה לשחזור הנכון. + איבדת את מפתח ההתאוששות שלך\? אתה יכול להגדיר אחד חדש בהגדרות. + שחזור הודעות + הזן מפתח שחזור + השתמש במפתח השחזור שלך כדי לפתוח את היסטוריית ההודעות המוצפנות שלך + אינך יודע את ביטוי הסיסמה לשחזור שלך, אתה יכול %s. + השתמש במפתח השחזור שלך + השתמש בביטוי הסיסמה לשחזור כדי לבטל את נעילת היסטוריית ההודעות המוצפנות שלך + מביא גרסת גיבוי … + אתה עלול לאבד גישה להודעות שלך אם אתה מתנתק או מאבד מכשיר זה. + האם אתה בטוח\? + מפתחות ההצפנה שלך מגובים כעת ברקע לשרת הבית שלך. הגיבוי הראשוני עשוי להימשך מספר דקות. + הגיבוי התחיל + שגיאה לא צפויה + מפתח שחזור + יצירת מפתח שחזור באמצעות ביטוי סיסמה, תהליך זה יכול להימשך מספר שניות. + שתף מפתח שחזור עם … + בבקשה צרו העתק + עצור + החלפה + נראה שכבר יש לך גיבוי מפתח הגדרה מהפעלה אחרת. האם אתה רוצה להחליף אותו לזה שאתה יוצר\? + גיבוי כבר קיים בשרת הבית שלך + מפתח השחזור נשמר. + מפתח השחזור נשמר ב- \'%s\'. +\n +\nאזהרה: קובץ זה עשוי להימחק אם הסרת ההתקנה של היישום. + שמירת קובץ בשם + שיתוף + שמור מפתח שחזור + הכנתי עותק + \ No newline at end of file diff --git a/vector/src/main/res/values-kab/strings.xml b/vector/src/main/res/values-kab/strings.xml index 27e8259efd..81cd4f4448 100644 --- a/vector/src/main/res/values-kab/strings.xml +++ b/vector/src/main/res/values-kab/strings.xml @@ -1,9 +1,8 @@ - + kab DZ Latn - Asentel aceɛlal Asentel n yiḍ Asentel aberkan @@ -13,10 +12,8 @@ Iɣewwaren Amazray Asenqed n tɣimit - Tebɣiḍ s tidet\? Asali… - IH Sefsex Sekles @@ -37,8 +34,6 @@ Asiwel urmid Ɣeṛ Agi - - Ur tesεiḍ ara tisirag ad tebduḍ asireg s usiwel deg texxamt-a Tukksa n uwiǧit ur teddi ara neɣ @@ -51,7 +46,6 @@ Ttu Senqed Agwi - Ffeɣ Tigawin Ffeɣ seg tuqqna @@ -61,28 +55,24 @@ Mdel Nɣel Sens - Asentem Asmigel Tuccḍa Yedda - Agejdan Ilɣa Ismenyifen Imdanen - Timɣiwent - Timɣiwnin - + Tixxamin + Tamɣiwnin Inced-d Tazwart taddayt Ilɣa n unagraw - Ulac igmad - Timɣiwent + Tixxamin Akaram n texxamt Nced - Timɣiwnin + Tamɣiwnin Azen iɣmisen Rnu ɣer texxamt Isem n useqdac @@ -90,7 +80,6 @@ Ffeɣ seg tuqqna URL n uqeddac n timagit Nadi - Ur yeddi ara usiwel ssebba n uqeddac ur nettuswel ara akken iwata Tiliɣri Uɣal ɣer deffir @@ -107,26 +96,21 @@ Awal uffir amaynut ilaq ad yettusekcem. Asenqed n tansa n yimayl ur yeddi ara: wali ma yella tsateḍ ɣef useɣwen yellan deg yimayl Asuter n tsarut yettwazen. - Aneẓli Alemmas Iḍelli Ass-a - Isawalen Asiwel yekfa Talɣut IH Kemmel - Sfeḍ Rnu Taskant Agi - Ffeɣ seg texxamt Snulfu-d - Srid Beṛṛa n tuqqna Arurmid @@ -138,12 +122,8 @@ Abder Ṣubb deg usellun-ik·im\? Ṣubb deg usellun - - Ttu - Taɣẓint - Nadi Azen izen yettuwgelhen… Azen tiririt yettuwgelhen… @@ -174,16 +154,12 @@ Tiliɣri Rnu uṭṭun n tiliɣri Rmed - Rmed - Rnu amiḍan - Amagnu Imesli i yilɣa Sens ilɣa i umiḍan-a Iznan yettwaznen s Bot - Lqem Izerfan ttwaḥerzen Ilɣa @@ -203,11 +179,9 @@ Asesteb Awal uffir: Azen - Iqqen am Aqeddac n timagit Amsefrak n umsidef - Imsidaf ttwasensen Agrudem n useqdac Tutlayt @@ -222,28 +196,23 @@ Fren Lbenna Yal tikkelt - Isem n texxamt Asmenyif Tazwart taddayt Ula yiwen - Ilɣa Anwa i izemren ad d-iɣer amazray\? Anwa i izemren ad d-yernu ɣer texxamt-a\? - Yal yiwen Iɛeggalen kan (segmi yebda ufran n textiṛit-a) Iɛeggalen kan (segmi ara d-ttwanecden) Iɛeggalen kan (segmi ara d-ttwarnun) - Ala imdanen i d-yettusnubegten Iseqdacen i yettwagin Talqayt Tinarimin Asulay n temɣiwent d arussin Asentel - Asulay n tqimit Asulay n tqimit Tasarut n tɣimit @@ -256,7 +225,6 @@ Kter Yettwasenqed ulac - Senqed Tabdart taberkant Asenqed n tɣimit @@ -265,7 +233,6 @@ %d n ulɣu %d n ilɣa - Taxxamt Nek Tuɣzi n tsefsit @@ -276,8 +243,6 @@ Asentel-inek·inem Asulay n yiwiǧit Asulay n texxamt - - Sireg Timerna n uwiǧit ulamek. Tuzna n usuter ur teddi ara. @@ -288,7 +253,6 @@ Senqed Bḍu Ttu - Ɣur-k·m! Tuccḍa n tladna Yeskan tigawt @@ -304,71 +268,55 @@ Rnu tamɣiwent Amedya amedya - Agejdan Imdanen - Timɣiwent - Timɣiwent + Tixxamin + Tixxamin Yettwancad Tettuḍ taxxamt - Sens amiḍan Sens amiḍan - Aqeddac-a agejdan iɛedda yiwet seg tlisa-ines tiɣbula. - Aqeddac-a agejdan yewweḍ ɣer talast n useqdac urmid n wayyur. - snefli fneẓ - Yal ass Sentem tafyirt tuffirt Sekcem tafyirt tuffirt Bdu aseqdec n uḥraz n tsarut Sifeḍ s ufus tisura - Immed Bḍu Semselsi Tebɣiḍ s tidet\? Tiririt seg uḥraz Kkes aḥraz - Kkes aḥraz Bdu aseqdec n uḥraz n tsarut - Akk tisura ttwaḥerzent Lqem Tuttra n usenqed i d-ikecmen Yettwasenqed! Iznan iɣellsanen akked useqdac-a ttwawgelhen seg yixef ɣer yixef yerna yiwen ur yezmir ad ten-iɣeṛ. Awi-t - Asuter n usenqed Ẓreg Err - Ɛreḍ tikkelt-nniḍen - Timɣiwent + Tixxamin Izen yettwakksen Sken-d iznan yettwakksen Beddel - Timɣiwent + Tixxamin Iznan usligen - Akaram n texxamt Amatu Ismenyifen Taɣellist & tbaḍnit Ameslaw & Tavidyut Tallalt & Ɣef - - Sken-d ineḍruyen yeffren deg uzray - Iznan usligen - Tiwtilin n useqdec Snifel aqeddac n timagit Afaylu @@ -382,7 +330,6 @@ Rnu inurifen Kkes seg yinuraf Aha bdu tura - Nniḍen Kemmel Jerred @@ -390,23 +337,17 @@ Γer sdat Imayl Awal uffir amaynut - Ɣur-k·m! Kemmel - Sneqdeɣ tansa-inu n yimayl - Tammug akken iwata! Awal uffir-inek/inem yettuwennez. Asmigel Imayl Imayl (Afrayan) Γer sdat - Γer sdat - Γer sdat - Isem n useqdac Awal uffir Γer sdat @@ -417,10 +358,8 @@ Awal uffir Sfeḍ isefka udmawanen Sfeḍ meṛṛa isefka - Iɣewwaren Yerna ¯\\_(ツ)_/¯ ɣer yizen n uḍris arewway - Msaḍan Ur msaḍan ara Afaylu @@ -435,11 +374,8 @@ Sagen Inced-d Iseqdacen - Ɛeddi ɣer tɣuri n wawwaḍ - Amazray - Awgelhen seg yixef ɣer yixef ur yeddi ara Rmed awgelhen\? Senqed anekcam-a @@ -447,22 +383,16 @@ Senqed Yettwasenqed Asmigel - Yettwattkal Ur yettwattkal ara - Ales awennez n tsura - Ih Uhu - Sentem tukksa Smiren - Anekcam amaynut. D kečč/kemm\? Tasarut-ik·im n uɛeddi Fakk - Awgelhen ur yeddi ara Awgelhen ur yermid ara Iznan ideg yella @taxxamt @@ -470,12 +400,9 @@ Iznan yettwawgelhen deg yidiwenniyen n ugraw Mi ara ttwaleqqment texxamin Yuzen izen d aḍris aččuran war ma isegza-t s tukksa n tecreḍt - Amiḍan-a yettuḥbes. - Yella uleqqem n uwgelhen Senqed iman-ik•im d wiyaḍ akken ad qqimen yidiwenniyen-ik•im d iɣellsanen - Seqdec tasarut n uɛeddi Ur yettwawgelhen ara Senqed ansi i d-tkecmeḍ @@ -490,11 +417,9 @@ Tura, Riot d aferdis! Sefesex tinnubga Asentel Status.im - Amtawi… Timesliwt i yineḍruyen Ilɣa s tsusmi - Talqayt n uɛeggal Aneqqis n wabug Talqayt n temɣiwent @@ -530,7 +455,6 @@ Talɣut ɣef tɣimit Timerniwt n uwiǧit ur teddi ara Izen yettwawgelhen - Imi xuṣṣent tsirag, izmer ur ttilint ara kra n tmahilin… Tesriḍ tisirag akken ad tebduḍ asarag deg texxamt-a Imi llant tsirag i ixuṣṣen, tigawt-a ur tezmir ara ad tili. @@ -547,7 +471,6 @@ Sizdeg ismawen n texxamin Ilɣa s ṣṣut Turagin n wis tlata - Sgunfu Asarag s usiwel iteddu \nRnu-d ɣer-s s %1$s neɣ s %2$s @@ -555,7 +478,6 @@ Sizdeg imttekkiyen Sizdeg ismawen n texxxamin Sizdeg ismawen n temɣiwnin - Idiwenniyen Adlis n tansiwin adigan Akaram n useqdac @@ -563,16 +485,13 @@ Ulac idiwenniyen Ur teǧǧiḍ ara Element ad yekcem ɣer yinermisen-ik·im idiganen Ulac aqeddac n timagit yettusiwlen. - Ulac tixxamin Ulac tixxamin tizuyaz yellan 1 useqdac %d yiseqdacen - Ulac igrawen - Azen iɣmisen n tuccḍa Azen tuṭṭfa n ugdil Ini ɣef wabug @@ -580,22 +499,17 @@ Ma yella wamek, ttxil-k·m aru aglam s teglizit. Glem-d ugur-ik·im da Zelzel reffu i tuzna n wabug - Yettwazen uneqqis n wabug akken iwata Ur nessaweḍ ara ad nazen aneqqis n wabug (%s) Asfari (%s%%) - Azen deg Ɣeṛ - Qqen URL n uqeddac agejdan Yebda udiwenni amaynut Yebda usiwel s taɣect Yebda usiwel s tvidyut - Azen s taɣuct - Tebɣiḍ s tidet ad tebduḍ adiwenni amaynut d %s\? Tebɣiḍ s tidet ad tebduḍ asiwel s taɣect\? Tebɣiḍ s tidet ad tebduḍ asiwel s tvidyut\? @@ -604,7 +518,6 @@ \nDeg wadeg n wayen, tzemreḍ ad tesqedceḍ aqeddac azayez ɣef %2$s, maca aya ur yettettkal ara fell-as, ad yebḍu tansa-ik·im IP d uqeddac-a. Tzemreḍ ad tesferkeḍ aya deg yiɣewwaren. Ɛreḍ aseqdec n %s Ur iyi-d-ssutur ara tikkelt-nniḍen - Asiwel s Element ur yeddi ara Fren ibenk n yimesli Amennay @@ -613,16 +526,13 @@ N sdat Sens HD Rmed HD - Azen ifuyla Azen astiker Ṭṭef-d tawlaft neɣ tavidyut Ṭṭef-d tawlaft Ṭṭef-d tavidyut - kemmel s… Suref-aɣ, ulac asnas yeffɣen yettwafen i wakken ad temmed tigawt-a. - Qqen Imayl neɣ isem n useqdac Isem n useqdac @@ -653,7 +563,6 @@ Tansa n yimayl i icudden ɣer umiḍan-ik·im ilaq ad tettwasekcem. Yettwazen yimayl ɣer %s: Akken ara tḍefreḍ aseɣwen-nni yellan deg-s, sit ddaw. Ttxil-k·m senqed syen qbel tisertiyin n uqeddac-a agejdan: - Ilaq ad yebdu URL s http[s]:// D awezɣi ad tkecmeḍ: tuccḍa deg uzeṭṭa Anekcum d awezɣi @@ -667,19 +576,15 @@ Tuccḍa deg SSL: ayugan n timagit ur yettwasenqed ara. Tuccḍa n SSL. Tabdart n yigrawen - Azen-aɣ-d Hraw Meẓẓiy - Sefsex asider\? Sefsex asali\? %d s %1$tesdidin %2$ds - Isem n texxamt Asentel n texxamt - Siwel Yeqqen asiwel Asiwel yetteqqen… @@ -691,51 +596,45 @@ Asiwel s tvidyut la iteddu… Rmed asiwel (%s) Uɣal ɣer usiwel - Yettwasekles UHU Tabdart n yiɛeggalen Amtawi… Ɛeddi ɣer yizen amezwaru ur nettwaɣra ara. - Tettwanecdeḍ ad ternuḍ ɣer %s taxxamt Adiwenni amaynut Rnu aɛeggal - 1 uɛeggal urmid + %d yiɛeggalen urmiden %d yiɛeggalen urmiden 1 uɛeggal - %d yiɛeggalen + %d yiɛaggalen 1 uɛeggal - - 1tasint + %dtsinin %dtsinin - 1tesdidt + %dtesdidin %dtesdidin - 1usrag + %dyisragen %dyisragen - 1wass - %dwussan + %dd + %dd - %1$s tura Seg %1$s %2$s - IFECKA N UNEDBAL SIWEL TIƔIMIYIN - Sefsex tinubga Ffeɣ si texxamt-a Kkes si texxamt-a @@ -747,19 +646,15 @@ Ur tettizmireḍ ara ad tesfesxeḍ asnifel-a acku tettṣubbuḍ deg usellun-unek·inem, ma yella d kečč·kemm i d aseqdac aneglam n texxamt-a, d awezɣi ad d-terreḍ ula d yiwet n tseglut. Zgel aseqdac Ur yettwazgel ara - "%1$s, " %1$s d %2$s %1$s %2$s - Snubget s usaulay INERMISEN IDIGANEN (%d) AKARAM N USEQDAC (%s) Iseqdacen kan n Matrix - Snubget-d iseqdacen s usulay Imayl neɣ asulay n Matrix - %s la yettaru… %1$s & %2$s la ttarun… %1$s & %2$s d wiyaḍ la ttarun… @@ -774,21 +669,18 @@ Kkes iznan ur yettwaznen ara Ur yettwaf ara ufaylu - 1 yizen amaynut + %d Izen amaynut %d yiznan imaynuten - Ur ttkal ara Adsil umḍin (%s): D awezɣi ad nsenqed timagit n uqeddac agemmaḍ. YETTWANCED YERNA - TIXXAMIN IZNAN IMDANEN IFUYLA - RNU AKARAM INURIFEN @@ -798,7 +690,6 @@ Rnu ɣer texxamt Rnu ɣer texxamt Aru asulay n texxamt neɣ isem yettunefken i texxamt - 1 texxamt %d texxamin @@ -806,7 +697,6 @@ Ffeɣ seg udiwenni Ttu Tasertit tabaḍnit - Tawlaft n umaɣnu Rnu tansa n yimayl Talɣut n usnas @@ -814,7 +704,6 @@ Seddu isekyaden Aselkem… (%1$d of %2$d) Ldi iɣewwaren - Iɣewwaren n umiḍan. Iɣewwaren n tɣimit. Iɣewwaren udmawanen. @@ -832,29 +721,22 @@ Ma yella ur mṣadan ara, taɣellist n teywalt-ik·im tezmer ad tettwaker. Aqeddac yezmer ad yili ulac-it neɣ iɛedda nnig uɛebbi Sɛan ṣṣut - Ikcemed deg Tugna n umaɣnu - I wakken ad tkemmle, ttxil-k·m sekcem awal uffir n umiḍan-ik·im: Ur ttamdal ara akk iznan iwgelhanen Aḥraz ue yezmir ara ad yekkes awgelhen s tsarut-a n uɛeddi: ttxil-k·m sefqed ma d tasarut n uɛeddi tameɣtut i teskecmeḍ. - Ur ttamdal ara akk iznan iwgelhanen Ur ttamdal ara akk iznan iwgelhanen Aḥraz n tsarut n useqdac - Tiririt n usnirem n uqeddac agejdan d tarameɣtut Idiwenniyen Tisedmirin Tisedmirin - Azayez Tisedmirin tiruradin - Ffeɣ seg tuqqna n uqeddac n timagit Yettraǧu - Issin ugar Tansa Imayl n usenqed ad yettwazen ɣer tbewwaḍt-ik·im n yimayl i usentem n yiɣewwaren n wawal-ik·im uffir. @@ -862,18 +744,13 @@ Aql-ak·akem teffɣeḍ seg meṛṛa tiɣimiyin syen ur d-teṭṭifeḍ ara akk ilɣa n Push. I wakken ad talseḍ armad n yilɣa, kcem tikkelt-nniḍen ɣef yal ibenk. Tiγimit tamirant Akken ara yettwarmad, awgelhen ur yettizmir ara ad yens. - Kečč / kem - Iznan deg texxamt-a ur ttwawgelhen ara seg yixef ɣer yixef. Issin ugar Ugar Ur yettwazgel ara - Akken ara yettwarmad, awgelhen ur yettizmir ara ad yens. - Tiɣimit-ik·im tamaynut dayen tettwasenqed tura. Ɣur-s anekcum ɣer yiznan yettwawgelhen, iseqdac-nniḍen daɣen ad asen-d-tban tettwattkal. - Anedbal-ik·im n uqeddac issens awgelhen seg yixef ɣer yixef s wudem amezwer deg texxamin tusligin & yiznan usriden. Tiɣimiyin S tidet tebɣiḍ ad tekkseḍ aneḍru-a\? Err deg uqerru-k·m ma yella tekkseḍ asnifel n yisem neɣ asentel n texxamt, yemzer asnifel-a ad yettusefsex. @@ -881,22 +758,16 @@ Ḥettem tiɣimit n ugraw ara d-yeffɣen akka tura deg texxamt tawgelhant ad tettwakkes Sentem timagit-ik·im s usenqed n yinekcam-a seg yiwet gar tɣimiyin-inek·inem-nniḍen, serreḥ-as ad tekcem ɣer yiznan yettwawgelhen. D awezɣi ad ternuḍ izen-inek·inem uslig. Ttxil-k·m senqed iseqdacen i tebɣiḍ ad d-tnecdeḍ syen ɛreḍ tikkelt-nniḍen. - Tutlayt tamirant Sebadu aḥraz aɣelsan - Seḥbiber iman-ik·im ɣef uḍegger n unekcum ɣer yiznann & yisefka yettwawgelhe s uḥraz n tsura n uwgelhen ɣef uqeddac-inek·inem. Tafyirt n tɣellist Asentel Ur yezmir ara ad yekkes awgelhen AWI-T ISSIN UGAR - aferdis - - Sekles tasarut n tririt deg - Rnu seg yidles n tiliɣri Idles-ik·im n tiliɣri d ilem Adlis n tiliri @@ -904,12 +775,9 @@ Tiririt n yinermisen-ik·im… Adlis-ik·im n yinermisen d ilem Adlis n yinermisen - Sefsex tinubga n %1$s\? - Yettwagi sɣur %1$s Asemmet n useqdac ur yeddi ara - Ilɣa push nsan Senqed iɣewwaren-ik·im i wakken ad tremdeḍ ilɣa push @@ -923,7 +791,7 @@ Asentem n tebzimt ur yeddi ara, ttxil-k·m aru yiwet. Sekcem PIN inek·inem Ttu PIN\? - Wennez tabzimt + Wennez PIN Tabzimt tamaynut n I uwennez n PIN-inek·inem, tesriḍ ad talseḍ anekcum syen rnu yiwen. Rmed PIN @@ -936,17 +804,13 @@ Ulac deg-s JSON ameɣtu Isem n useqdac-a yettwaseqdac yakan Aseɣwen n yimayl iɣef mazal ur yettusit ara fell-as - Ales asuter n tsura n uwgelhen seg tɣimiyin-ik·im tiyaḍ. - Asuter yettwazen Ɣeṛ tabdart n wawwaḍ - 1 usnifel deg umulteɣ %d yisnifal deg umulteɣ - Sewḥel isawalen iɣef ur tebniḍ Suter i usentem send beddu n usiwel Sireg aqeddac n tallalt n yisawalen n usellek @@ -957,19 +821,17 @@ Asefsex n useqdac Talqayt n texxamt - 1 i yettufernen - %d i yettufernen + %d i yettwafernen + %d i yettwafernen Sefsex Asali Sefsex Asider - Nadi akaram %1$s taxxamt yettwafen i %2$s %1$s taxxamin yettwafen i %2$s Anadi n ukaram… - Ibdaren kan Tabaḍnit n yilɣa Ilɣa n usellek @@ -987,15 +849,12 @@ Isem n temɣiwent Asulay n temɣiwent Ulac iseqdacen - Sizdeg iɛeggalen n ugraw Sizdeg tixxamin n yigrawen - 1 uɛeggal %d yiɛaggalen - 1 texxamt %d texxamin @@ -1005,35 +864,28 @@ Avaṭar n wawwaḍ Avaṭar n ulɣu Senqed tura - %1$s: %1$s: %2$s +%d %d+ Ḥbes - Tasarut tririt D nekk - Alguritm Azmul - Wali asuter Asenqed n tsarut Asuter yettwasefsex Tuccḍa tarussint - Yettwanced-d sɣur %s - Qbel Ḥemmel Rnu taxxamt tamaynut Snifel azeṭṭa Meṛṛa timɣiwnin - Taxxamt tamaynut RNU - Isem n texxamt + Isem Yal yiwen yezmer ad yernu ɣer texxamt-a Lqem SDK n Matrix Amussnaw @@ -1044,25 +896,18 @@ tiɣimit_isem: Url: Amasal: - Sekles ajuṭu - Eg asumer Ttxil-k·m aru asumer-ik·im ddaw. Yettaru… (yettwaẓreg) - Tiẓrigin n yizen Ulac tiẓrigin yettwafen - Sizdeg idiwenniyen… Isem neɣ asulay (#example:matrix.org) - Rnu s usulay n Matrix Timerna n texamt… Ɣeṛ deg - - Aqeddac n timagit Sken awal uffir Ffer awal uffir @@ -1077,44 +922,35 @@ 1 useqdac yeɣra %d yiseqdacen ɣran - Afaylu \'%1$s\' (%2$s) ɣezzif aṭas i usali. Talast d %3$s. - Tuccḍa deg tuqqna lawan n uneɛruḍ n uceqquf yeddan. Ameslaw Astiker Ur yezmir ara ad ttusqedcen deg yisefka n beṭṭu - AMIDYA Ulac amidya deg texxamt-a IFUYLA %1$s ɣer %2$s Ulac ifuyla deg texxxamt-a - D aspam Aneqqis udmawan… Taɣzint i tuzna n ugbur-a ANEQQIS ZGEL ASEQDAC - Agbur yettwazen Yettwazen d aspam Zgel aseqdac - Ibdaren kan Ffeɣ si texxamt %1$s ur iga ara akk isnifal Ur tgiḍ ara akk isnifal Aru n wawalen ufranen i tifin n tsedmirt. - Ur tezgileṣ ula d yiwen useqdac - %1$s yerra taxxamt d tazayazt i kra n win yessnen aseɣwen. Terriḍ taxxamt d tazayazt i kra n win yessnen aseɣwen. %1$s yerra taxxamt s tinubga kan. Terriḍ taxxamt s tinubga kan. Iznan ur nettwaɣra ara - D adiwenni-inek·inem. Ṭṭef-itt. Mmeslay d yimdanen srid neɣ deg ugraw Eǧǧ idiwenniyen d usligen s uwgelhen @@ -1122,20 +958,15 @@ Qqen ɣer %1$s Kcem ɣer %1$s Kemmel s SSO - Tansa n yimeẓla n Element Matrix Sekcem tansa n uqeddac i tebɣiḍ ad tesqedceḍ - Imayl-a ur iqqin ula ɣer yiwen n umiḍan. - Wennez awal uffir ɣef %1$s Ulac amiḍan akk amiḍan wuɣur yeqqen yimayl-a - Senqed tabewwaḍt-ik·im n yimayl Imayl n usenqed yettwazen ɣer %1$s. Sit ɣef useɣwen i usentem n wawal-ik·im uffir. Akken ara tḍefreḍ aseɣwen i yellan deg-s, sit ddaw. Tuɣalin ɣer unekcum - Sbadu tansa n yimayl Sbadu uṭṭun n tiliɣri Uṭṭun n tiliɣri @@ -1150,52 +981,41 @@ Fren imeẓla n Element Matrix Fren aqeddac agejdan udmawan Qbel tiwtilin i wakken ad tkemmleḍ - Ttxil-k·m senqed imayl-ik·im Kcem s usulay n Matrix Kcem s usulay n Matrix Yemmẓer sɣur - Aql-ak·akem teffɣeḍ Kcem tikkelt-nniḍen - Aql-ak·akem teffɣeḍ Sfeḍ isefka Sfeḍ isefka Aglam wezzil aṭas - Amtawi amezwaru… - Ẓer meṛṛa tiɣimiyin-inu Iɣewwaren leqqayen Askar aneflay Azlaz yettwaf-d! Tiɣimiyin tiyaḍ - Rmed awgelhen Mačči d aɣelsan Tavidyut. Tugna. Ameslaw Astiker - Yettṛaǧu… %s yettwasefsex %s yettwaqbal Asenqed yettwazen Yettwasenqed s ufus - Siggez tangalt-a Ttxil-k·m sekcem tasarut n tririt - Asirew n tsarut SSSS seg tefyirt tuffirt Asirew n tsarut SSSS seg tefyirt tuffirt (%s) Asirew n tsarut SSSS seg tsarut n tririt %1$s (%2$s) - Ur yezmir ara ad isekles afaylu n umidya Sbadu awal uffir amaynut n umiḍan… - Element Web \nElement Desktop Element iOS @@ -1205,17 +1025,13 @@ Seqdec %1$s-inek·inem neɣ seqdec %2$s-inek.inem i wakken ad tkemmleḍ. Aḥraz ur yezmir ara ad yekkes awgelhen s tsarut-a n tririt: ttxil-k·m sefqed ma d tasarut n tririt tameɣtut i teskecmeḍ. Anekcum ɣer uklas aɣelsan ur yeddi ara - Yettuwgelhen s yibenk ur nettwasenqed ara Senqed anekcam amaynut i ikecmen ɣer umiḍan-ik/im: %1$s - Senqed anekcam Creḍ yettwaḍman - Qbel Agwi Ɛelleq - Ttxil-ik·im fren isem n useqdac. Ttxil-ik·im fren awal uffir. Rnu iɛeggalen @@ -1229,10 +1045,8 @@ Tinubga tettwazen i %1$s d %2$d d wiyeḍ Ur nezmir ara ad d-nesnubget iseqdacen. Ttxil-k·m wali iseqdac i tebɣiḍ ad d-tesnubegteḍ syen ɛreḍ tikkelt-nniḍen. - Tutlayin-nniḍen yellan Sali-d tutlayin yellan… - Ldi tiwtilin n %s Seqdec %1$s Sbadu tamlilt @@ -1242,30 +1056,23 @@ Kkes asgugem i usawaḍ Seḥbes takamiṛat Senker takamiṛat - Aḥraz aɣelsan Seqdec tasarut n tɣellist Sirew tasarut n tɣellist ara tḥerzeḍ deg wadeg yettwaḍemnen, am yimsefrak n wawalen uufiren neɣ deg usenduq. Sbadu tafyirt taɣelsant Kles tasarut-ik·im n tɣellist deg wadeg yettwaḍemnen, am umsefrak n wawalen uffiren neɣ neɣ usenduq. - Kles tasarut-ik·im n tɣellist deg wadeg yettwaḍemnen, am umsefrak n wawalen uffiren neɣ neɣ usenduq. - Tbeddleḍ iɣewwaren n texxamt akken iwata - Ur tezmireḍ ara ad tkecmeḍ ɣer izen-a Aṛaǧu i umazray n uwgelhen - Asnas yerreẓ tikkelt-nni taneggarut. Tebɣiḍ ad teldiḍ agdil n uneqqis n truẓi\? Akka tura ur tesɛiḍ ara akemmus n yistiker yettwaremden. \n \nRnu yiwen tura\? - Sefsex tinubga Taɣzint i tuzna n ugbur-a Talɣut ɣef tɣimit Fren tamurt - Ttxil-k·m fren tamurt Uṭṭun n tiliɣri Uṭṭun n tiliɣri d arameɣtu i ufran n tmurt @@ -1275,7 +1082,6 @@ Tuccḍa mi ara nessentam uṭṭun-ik·im n tilifun Tella-d tuccḍa mi ara nessenqad uṭṭun-ik·im n tilifun. Talut-nnien: %s - Asekkussem amezwer Taɣbalut n umidyat amezwer Asentel @@ -1284,19 +1090,16 @@ 1 texxamt %d texxamin - %1$s: %2$s Meẓẓiy Hraw Ttxil-k·m sekcem tasarut n tririt Rmed awgelhen - Ayagi yezmer ad yeṭṭef kra n wakud, ttxil-k·m ṣṣber. Asbadu n tririt. Tsuliḍ! Eǧǧ-it d aɣelasn Seqdec wa %1$s d azeṭṭa aɣelsan mi ara tettuḍ %2$s-inek·inem. - Asuffeɣ n tsura n timagit yettwarnan Asirew n tsarut n tɣellist seg tefyirt tuffirt Asbadu n tsarut s wudem amezwar n SSSS @@ -1304,18 +1107,13 @@ Amtawi n tsarut n useqdac Amtawi n tsarut n uzmul asuf Asbadu n uḥraz n tsarut - - %2$s & %1$s inek·inem ttusbadun tura. \n \nEǧǧ-iten d iɣelsanen! Ad ten-teḥwiǧeḍ ad teldiḍ iznan yettwawgelhen d telɣut n tɣellist ma yella tesruḥeḍ akk tiɣimiyin-ik·im yettwaremden. - <b>Siggez-itt syen kles-itt deg wadeg aɣelsan Sekles-itt ɣef tsarut USB neɣ deg yibenk n uḥraz Nɣel-itt ɣer uklas-ik·im n usigna udmawan - Ur tezmireḍ ara ad tgeḍ aya seg uziraz - Asbadu n tefyirt tuffirt n tririt ad ak·am-teḍmen taɣellist & tawaledyawt n yiznan yettwawgelhen, yettwattkalen. \n \nMa yella ur tebɣiḍ ara ad tesbaduḍ awal uffir n yizen, sirew deg wadeg-is tasarut n yizen. @@ -1333,9 +1131,7 @@ Aṭas n yisuturen i yettwaznen Awennez n tkamiṛat d awezɣi tiririt ɣef usiwel seg wadeg-nniḍen - Ur yezmir ara ad isekles tavidyut - Element yesra tasiregt n unekcum ɣer temkarḍit-inek·inem n tewlafin d tvidyut i tuzna d usekles n tceqqufin yeddan. \n \nMa ulac aɣilif sireg anekcum deg yisfuyla udhimen i d-iteddun i wakken ad tizmireḍ ad tazneḍ ifuyla seg tiliɣri-inek·inem. @@ -1353,9 +1149,7 @@ Element yezmer ad issenqed adlis-inek·inem n tansiwin i wakken ad d-yaf iseqdacen-nniḍen n Matrix s usenned ɣer yimaylen d wuṭṭunen n tiliɣri nsen. \n \nTebɣiḍ ad tebduḍ adlis-inek·inem n tansiwin i yiswi-a\? - Nesḥassef. Tiggawt-a ur tezmir ara ad d-tili imi llant tsirag i ixuṣṣen - Sekles i usali\? Ldi aqerru Tinubga-a tettwazen i %s, ur ncudd ara ɣer umiḍan-a. @@ -1366,22 +1160,18 @@ Tiwtilin & tfadiwin Sentem awal-ik·im uffir Asesteb yettusra - Tansiwin n yimayl Uṭṭunen n tiliɣri Kkes %s\? Azal n wulu s uneḍru - Iɣewwaren n unagraw. Ilɣa ttwaremden deg yiɣewwaren n unagraw. Ilɣa ttusensen deg yiɣewwaren n unagraw. \nMa ulac aɣilif senqed iɣewwaren n unagraw. Ilɣa ttwaremden i umiḍan-ik·im. Senqed iɣewwaren - Asenqed n yimeẓla n tɣuri Seqɛed imeẓla n tɣuri - Ajuṭu Firebase Tiririt n ujuṭu FCM tedda akken ilaq: \n%1$s @@ -1389,14 +1179,11 @@ \n%1$s Asekles n ujuṭu Senker ameẓlu - Bdu seg tazwara Swel ilɣa n zzhir Swel ilɣa n usiwel Swel ilɣa n tsusmi Fren ini, tasmamayt, imesli n LED… - - Iznan ideg yella yisem-iw n useqdac Iznan deg usqerdec gar sin kan Iznan n yisqerdicen n ugraw @@ -1405,14 +1192,11 @@ Ulac amtawi n ugilal Bdu seg usenker Rmed amtawi n ugilal - Tiwtilin & tfadiwin Sfeḍ takatut tuffirt %1$s @ %2$s Fren tutlayt - Awalen uffiren ur mṣadan ara - Tamurt 3 wussan 1 wayyur @@ -1420,20 +1204,14 @@ Awgelhen seg yixef ɣer yixef Akaram Tuccḍa deg uglam - Tinubga tamaynut %1$s: %2$s %3$s - Nadi amazray - Ahrawan Ahrawan akk Meqqer - WALI Rmed iwiǧiten - - Awiǧit Sali awiǧit Awiǧit-a yettwarna sɣur: @@ -1443,7 +1221,6 @@ Ales asali n yiwiǧit Ldi deg yiminig Sefesex anekcum i nekk - Sewḥel kullec Ixuṣṣ usulay_taxxamt deg usuter. Ixuṣṣ usulay_aseqdac deg usuter. @@ -1458,25 +1235,18 @@ Ttxil-k·m sekcem awal-ik·im uffir. Adiwenni yettkemmil da Sit da i wakken ad twaliḍ iznan iqburen - Talast n yiɣbula tettuɛedda Nermes anedbal - Ma ulac aɣilif %s kemmel aseqdec n umeẓlu-a. - Nesḥassef, tella-d tuccḍa - Sken tamnaḍt n telɣut I tuccḍiwin kan - Rnu tafyirt tuffirt Tafyirt tuffirt ur temṣada ara Ma ulac aɣilif sekcem tafyirt tuffirt Tafyirt tuffirt ur teǧhid ara aṭas - Ma ulac aɣilif kkes tafyirt tuffirt ma yella tebɣiḍ Element ad isirew tasarut n tririt. Ulac tiɣimit n Matrix i yellan - (Leqqayen) Sbadu tafyirt tuffirt Timerna n uḥraz @@ -1485,78 +1255,59 @@ Sekles tasarut n tririt Sekles am ufaylu Tasarut n tririt tettwasekles. - Yella yakan uḥraz deg uqeddac-ik·im agejdan Ma ulac aɣilif, eg anɣal Bḍu tasarut n tririt d… Aḥraz yebda seqdec tasarut-ik·im n tririt Tiririt n yizen - Serreḥ i umazray Kkes aḥraz… Aḥraz n tsarut amaynut Aseɣwen yettwanɣel \'ɣef wafus\' - Tangalt Ittraju %s… Isuli-d Isefka n umiḍan Taxtirit yettefernen Anekcum amaynut - Sekcem tasarut tuffirt n uḥraz uffir Ɣur-k·m: Tisur ttwaleqqment yakan! - Element Android - Isutar n tsura - Ittraju %s… - Tifrat n wugur Afaylu n useqdac - Kcem %s Tuqqna n umidyat ur teddi ara Ṭṭef-d tawlaft neɣ tavidyut Element yesra tasiregt n unekcum er tkamiat-ik·im i wakken ad d-yeṭṭef tawlafin d yisawalen s tvidyut. Yal win·tin yessnen aseɣwen n texxamt, slid inebgawen Yal win·tin yessnen aseɣwen n texxamt rnu-d ɣer-sen inebgawen - %d yezgel aseqdac %d yezgel iseqdacen - Asulay n texxamt tagensant Awgelhen seg yixef ɣer yixef yettwarmed Tesriḍ ad teffɣeḍ i wakken ad tizmireḍ awgelhen. Wgelhen i usenqed n tɣimiyinkan Ur ttazen ara akk iznan yettwawgelhen ɣer tɣimiyin ur nettusenqad ara deg texxamt-a, seg tɣimit-a. - Tansa tamaynut (am. #foo:matrix.org) - Asulay n temɣiwent tamaynut (am. #foo:matrix.org) \'%s\' mačči d asulay n temɣiwent ameɣtu - - Ur tesɛiḍ ara tansa tagejdant yettwafernen i texxamt. Tansa tagejdant terreẓ - Sbadu tansa tagejdant Tansa tagejdant ur tettusbadu ara Asulay n unɣal n texxamt Tansa n unɣal n texxamt - Awgelhen yettwarmed deg texxamt-a. Awgelhen yettusens deg texxamt-a. Rmed awgelhen \n(Ɣur-k·m: ur yezmir ara ad yettusens tikkelt-nniḍen!) - Talɣut n uwgelhen seg yixef ɣer yixef - Talɣut n uneḍru Asulay n useqdac Tasarut n timagit Curve25519 @@ -1565,17 +1316,14 @@ Isem azayez (yettban i yimdanen wukud tettmeslayeḍ) Isem azayez Udsil umḍin Ed25519 - Sifeḍ tisura n ufaylu adigan Ma ulac aɣilif rnu tafyirt tuffirt i uwgelhen n tsura yettwasifḍen. Tesriḍ ad teskecmeḍ tafyirt-nni kan tuffirt i wakken ad tizmireḍ ad d-tketreḍ tisura. Tisura n texxamt E2E ttwaseklasent deg \'%s\'. \n \nƔur-k·m: afaylu-a yezmer ad yettwakkes ma yella asnas ur yettusebded ara. Asifeḍ n tsura yedda akken iwata - Tiririt n yiznan yettwawgelhen Sefrek aklas n tsura - Kter tisura n ufaylu adigan Wgelhen i usenqed n tɣimiyinkan Ur ttazen ara akk iznan yettwawgelhen ɣer tɣimiyin ur nettusenqad ara seg tɣimit-a. @@ -1583,27 +1331,22 @@ %1$d/%2$d tasarut tettwasifeḍ akken iwata. %1$d/%2$d tisura ttwasifḍen akken iwata. - Ur yettwasenqed ara Deg tebdart taberkant - tiɣimit tarussint ip arussin Ur yettusenqed ara Kkes seg tebdart taberkant - Taxxamt ideg llant tɣimiyin tarussanin Taxxamt-a deg-s tiɣimiyin tarussinin ur nettwasenqed ara. \nAya yebɣa ad d-yini ulac aḍman belli tɣimiyin-a d tidet n yiseqdacen i d-temmal. \nAd ak·akem-nwelleh ad tuɣaleḍ ɣer ukala n usenqed n yal tiɣimit send akemmel, maca tzemreḍ ad talseḍ tuzna n yizen war asenqed ma yella tebɣiḍ. \n \nTiɣimiyin tarussinin: - Fren akaram n texxamt Aru aqeddac agejdan i wakken ad d-tbedreḍ tixxamin tizuyaz seg-s Tixxamin meṛṛa ɣef uqeddac %s Aru da… - %1$s: 1 yizen %1$s: %2$d yiznan @@ -1627,9 +1370,9 @@ Seqdec taqeffalt n unasiw Kcem i tuzna n yizen Taxtiṛit-a tesra asnas n wis tlata i usekles n yiznan. I wakken ad tkemmleḍ tesriḍ ad tqebleḍ tiwtilin n umeẓlu-a. - Terniḍ tiɣimit tamaynut \'%s\', i yessuturen tisura n uwgelhen. - Tiɣimit tamaynut tessutur tisura n uwgelhen. Isem n tɣimit: %1$s + Tiɣimit tamaynut tessutur tisura n uwgelhen. +\nIsem n tɣimit: %1$s \nTimeẓriwt taneggarut: %2$s \nMa yella ur tekcimeḍ ara ɣer tɣimit-nniḍen, ttu asuter-a. Tiɣimit-inek·inem ur tettwasenqed ara \'%s\', tessutur tisura n uwgelhen. @@ -1637,9 +1380,7 @@ \nIsem n tɣimit: %1$s \nTimeẓriwt taneggarut: %2$s \nMa yella ur tekcimeḍ ara ɣer tɣimit-nniḍen, ttu asuter-a. - I uṣeggem n usefrek n yisnasen n Matrix - Akka d-yettban tetthuzzuḍ tiliɣri s lxiq. Tebɣiḍ ad teldiḍ agdil i tuzna n wabug\? Sbadu imayl i tririt n umiḍan, syen ɣer sdat ad yishil ad tt-afen yimdanen i ak·akem-yessnen. Sbadu uṭṭun n tiliɣri, syen ɣer sdat ad yishil ad t-afen yimdanen i ak·akem-yessnen. @@ -1649,14 +1390,11 @@ \n \nIlaq-ak·am ad ternuḍ imayl-ik·im ɣer umaɣun-inek·inem deg yiɣewwaren. Ibenk-inek·inem yesseqdac aneggaf n tɣellist TLS aqbur, yemzer i uḍfar s waṭas, i tɣellist-inek·inem ur tettizmireḍ ara a teqqneḍ - Ma ulac aɣilif err Element deg yibenk-nniḍen i izemren ad yekkes awgelhen i yiznan, akken ad yizmir ad yazen tisura ɣer tɣimit-a. - Seqdec taṭenṭunt n Element tamezwert i yisawalin ara d-ikecmen Ad isseqdec %s d tallalt mi ara yili uqeddac-ik·im agejdan ur d-imudd ara yiwen (tansa-inek·inem IP ad tettwabḍu ayen akk ara yeqqim usiwel) Taṭenṭunt n usiwel i d-ikecmen Fren asṭeṭen i yisawalen: - Agalis anmeggag ur yessaweḍ ara ad yerfed. Matrix yezmer ad isenqed adlis-ik·im n tansiwin i wakken ad yaf iseqdacen-nniḍen n Matrix s ttawil n yimaylen d wuṭṭunen n tiliɣri nsen. Ma yella tqebleḍ ad tebduḍ adlis-ik·im n tansiwin i waya, ma ulac aɣilif sireg anekcum deg yisfuyla udhimen i d-iteddun. Rnu aqeddac n timagit deg yiɣewwaren-ik·im i wakken ad tesnetmeḍ tigawt-a. @@ -1664,7 +1402,6 @@ Tebɣiḍ s tidet ad tekkseḍ %s seg udiwenni-a\? Ur tettizmireḍ ara ad tesfesxeḍ asnifel-a acku tessebɣaseḍ aseqdac ad yesɛu aswir n tezmert am kečč·kemm. \nTebɣiḍ s tidet\? - Azgal n useqdac-a ad yekkes iznan-ines seg texxamin i tebḍiḍ. \n \nTzemreḍ ad tbeddleḍ tigawt-a melmi i tebɣiḍ deg yiɣewwaren imuta. @@ -1675,7 +1412,6 @@ \nAkken ur tettɛemmideḍ ara attekki-nsen tikkelt-nniḍen, ilaq ad t-tagiḍ xiṛ. Tegtin n useqdac ad t-isuffeɣ seg texxamt-a rnu ur as-yettɛemmid ara ad yettekki tikkelt-nniḍen. Tukksa n tigtin i useqdac ad t-teǧǧ ad ittekki deg texxamt tikkelt-nniḍen. - Tebɣiḍ s tidet ad d-tnecdeḍ %s ɣer udiwenni-a\? Ma ulac aɣilif sekcem yiwet neɣ ugar n tansiwin n yimayl neɣ asulay n Matrix Aya yebɣa ad d-yini yellawin d ugur i tikli-inek·inem s yir udem, neɣ tiliɣri-inek·inem ur yettkil ara ɣef uselkin i as-imudd uqeddac anmeggag. @@ -1684,19 +1420,16 @@ \n \nẒer belli tigawt-a ad tales asenker n usnas yerna ad yeṭṭef kra n wakud. Rnu anegzum n ugdil agejdan - Turagin n wis tlata Ulac uṭṭun n tiliɣri i yettwarnan ɣer umiḍan-inek·inem Sken talɣut n usnas deg yiɣewwaren n unagraw. Ur tezmireḍ ara ad tgeḍ aya seg Element n uziraz Ulac imayl yettwarnan ɣer umiḍan-ik·im Ttkel tettekkaḍ ɣef useɣwen yellan deg yimayl i ak·am-n-uznen. - Iɣewwaren n yilɣa leqqayen Tasleḍt n taffa tgerrez. Ma mazal ur d-tremseḍ ara ilɣa, ttxil-k·m azen aneqqis n wabug i wakken ad aɣ-talleḍ ad nefru ugur. Yiwen neɣ ugar n yisekyaden ur ddin ara, ɛreḍ iwellihen i d-yettwasumren. Yiwen neɣ ugar n yisekyaden ur ddin ara, ma ulac aɣilif azen aneqqis n wabug i wakken ad aɣ-talleḍ ad nefru ugur. - Ilɣa ttwasensen i umiḍan-inek·inem. \nMa ulac aɣilif senqed iɣewwaren n umiḍan. Ttwaremden yilɣa i tɣimit-a. @@ -1711,7 +1444,6 @@ Ajuṭu FCM yettwasekles akken iwata ɣef uqeddac agejdan. Asekles n ujuṭu FCM ɣef uqeddac agejdan ur yeddi ara. \n%1$s - Ameẓlu n yilɣa Ameẓlu n yilɣa la iteddu. Ameẓlu n yilɣa ur iteddu ara. @@ -1719,11 +1451,9 @@ Ameẓlu n yilɣa yules asenker s wudem awurman Ameẓlu yettwanɣa syen yules asenker s wudem awurman. Allus n usenker n umeẓlu ur yeddi ara - Ameẓlu ad yenker mi ara yales yibenk asenker. "Ameẓlu ur yettenker ara mi ara yales yibenk asenker, ur d-tremseḍ ara ilɣa alamma yettwaldi Element xerṣum yiwet n tikkelt." Rmed asenker seg tnekra - Senqed ilugan n ugilal Iluggan n ugilal ttusensen i Element. Asekyed-a ilaq ad yeddu s useqdec n yisefka n uziraz (ulac WIFI). \n%1$s @@ -1732,17 +1462,14 @@ \n \n%1$s Sens ilugan - Asefrer n tbatrit Anef i usefrer - Isnasen ur srin ara ad qqnen ɣer uqeddac agejdan deg ugilal, ilaq ad tesneɣseḍ aseqdec n uẓru • Ilɣa ttwaznen s Firebase Cloud Messaging • Ala ilɣa kan ideg llan isefka n udfer • Agbur n yizen n wulɣ yettusres s wudem aɣelsa srid seg uqeddac agejdan n Matrix • Ilɣa ideg yella isefka n udfer d yizen • Ilɣa ur d-skanayen ara agbur n yizen - Rmed ilɣa i tɣimit-a Cɛel agdil deg 3 tsinin Iznan ideg yella yisem-iw yettwaskanen @@ -1753,8 +1480,6 @@ Yettusesfer i wakud ilaw Ur d-tetteṭṭfeḍ ara ulɣu n yiznan i d-ikecmen ma yili asnas ɣef ugilal i yella. Aleqqem n yiɣewwaren ur yeddi ara. - - Yemmed wakud n usuter n umtawi Yesmenyaf azilal n umtawi %s @@ -1764,7 +1489,6 @@ Turagin n wis tlata Ḥrez amidyat Sfeḍ tuffirt n umidyat - Iɣewwaren n useqdac Imsidaf Asefrek n tsur n uwgelhen @@ -1795,32 +1519,26 @@ Sbadu ɣef yibenk-a Sirew tasarut n tɣellist tamaynut neɣ sbadu tafyirt n tɣellist i uḥraz-inek·nem yellan. Aya ad yuɣal deg ubdil n tsarut-ik·im neɣ n tefyirt-ik·im tamirant. - Sens amiḍan-inu Sefrek iɣewwaren-inek·inem n usnirem. Tabaḍnit n wulɣu Mudd tasiregt Fren taxtiṛit-nniḍen - Tuqqna n ugilal Mudd tasiregt - Element ileqqeḍ tasleḍt tudrigt i wakken ad aɣ-iɛawen ad nesnerni asnas. Ma ulac aɣilif rmed tasleḍt i wakken ad aɣ-ɛiwnent ad nesnerni Element. Ih, bɣiɣ ad d-muddeɣ tallalt! - Askar n usekles n yisefka Leqqem isem azayez Aqeddac agejdan Sireg imsidaf Rmed \'imsidaf n usefrek\' deg yiɣewwaren i tigin n waya. - Ulamek akk tettwasenqed tansa n yimayl. Ma ulac aɣilif senqed imayl-inek·inem syen sit ɣef useɣwen yellan deg-s. Akken ara tgeḍ aya, sit i wakken ad tkemmleḍ. Tansa-agi n yimayl tettuseqdac yakan. Tansa-a n yimayl ulac-it. Uṭṭun-agi n tilifun yettuseqddac yakan. Tella-d tuccḍa mi ara nessenqad tansa-inek·inem n yimayl. - Leqqem awal uffir Aleqqem n wawal uffir ur yeddi ara Awal uffir mačči d ameɣtu @@ -1830,19 +1548,13 @@ \nẒer belli tigawt-a ad yales asenker n usnas yerna yezmer ad yeṭṭef kra n wakud. Imdanen d wuṭṭunen n tiliɣri Sefrek imaylen d wuṭṭunen n tiliɣri i icudden ɣer umiḍan-ik·im Matrix - "Tebɣiḍ s tidet ad tekkseḍ alɣu-a \?" - Tebɣiḍ s tidet ad tekkseḍ %1$s %2$s\? - Urar s umeslaw - Akka tura ur telliḍ ara d aɛeggal ula deg yiwet temɣiwent. - Tawlaft n texxamt Tabzimt n texxamt Yettucreḍ d: - Anekcum d tmeẓriwt Err taxxamt-a deg tebdart n ukaram n texxamt Anekcum n texxamt @@ -1852,9 +1564,7 @@ \'%s\' mačči d amasal ameɣtu i yisem yettwamudden Tasarut n udsil umḍin Ed25519 tettusra La ssenqadeɣ tisura-a ma mṣadant - Tixxamin meṛṛa tidiganin %s - 1 yizen i d-yettwalɣu ur yettwaɣra ara %d yiznan i d-yettwalɣun ur ttwaɣran ara @@ -1865,19 +1575,15 @@ Rnu isaragen s usiwel s jitsi Ɣer amidyat yemmestnen s DRM - Bdu s tkamiṛat n unagraw deg ubdil n ugdil n tkamiṛat tudmawant. Asarag s usiwel ha-t-an iteddu, ur yezmir ad yettwattkal fell-as. - Taladna tarussint: %s Taladna \"%s\" tesra ugar n yiɣewwaren, neɣ kra n yiɣewwaren d arimeɣta. Kkes azgal i useqdac s usulay i d-yettunefkan Rmed/Sens Markdown Tacreḍt yeɣlin tettwarmed. Tacreḍt yeɣlin tettusens. - Anedbal n temɣiwent ur d-imudd ara aglam ɣezzifen i temɣiwent-a. - Tettusuffɣeḍ-d seg %1$s sɣur %2$s Tettusuffɣeḍ-d seg %1$s sɣur %2$s I wakken ad tkemmleḍ aseqdec n uqeddac agejdan %1$s, ilaq ad talseḍ asenqed syen ad tqebleḍ tiwtilin-nneɣ s umata. @@ -1885,14 +1591,12 @@ Taxxamt-a tettusmelsi, dayen d tarurmidt Taxxamt-a d akemmel n udiwenni-nniḍen nermes anedbal n umeẓlu-inek·inem - Aqeddac-a agejdan iɛedda yiwet seg tlisa-ines n teɣbalut ɣef waya kra n yiseqdacen ur ttizmiren ara ad kecmen. Aqeddac-a agejdan yessaweḍ talast-is n useqdac n wayyur urmid ɣef waya kra n yiseqdacen ur ttizmiren ara ad kecmen. Ma ulac aɣilif %s i usnerni n talast-a. Asali n yiɛeggalen n texxamin ẓẓayen I yiznan d tuccḍiwin Ulac APK imeɣta n yimeẓla n Google Play i yettwafen. Ilɣa ur zmiren ara ad ddun akken iwata. - Iznan deg texxamt yettwawgelhen, ttusɣelsen s uwgelhen n yixef ɣer yixef. Ala kečč·kemm d uɣerwaḍ (yiɣeryaḍen) i yesɛan tisura i tɣuri n yiznan-a. \n \nAḥraz aɣelsan n tsura-inek·inem i akken tḍemneḍ ur ak·am-ttruḥun ara. @@ -1909,20 +1613,14 @@ Asirew n tsarut n tririt s useqdec n tefyirt tuffirt, akal-a yezmer ad yeṭṭef ddeqs n tsinin. Tuccḍa u nettwarǧa ara Tisura-inek·inem n uwgelhen ha-tent-an tura ttwaḥrazent deg ugilal ɣef uqeddac-ik·im agejdan. Aḥraz agejdan yezmer ad yeṭṭaf ddeqs n tesdidin. - - Yezmer tesruḥeḍ anekcum ɣer yiznan-ik·im ma yella teffɣeḍ neɣ tesruḥeḍ ibenk-a. - Seqdec tafyirt-ik·im n tririt i twaledyawt n umazray n yiznan-ik·im yettwawgelhen Ur tessineḍ ara tafyirt-ik·im tuffirt n tririt, tzemreḍ %s. - Seqdec tasarut-ik·im n tririt i twaledyawt n umazray n yiznan-ik·im yettwawgelhen Sekcem tasarut tririt - Tesruḥeḍ tasarut-ik·im n tririt\? Tzemreḍ ad tesbaduḍ yiwet seg yiɣewwaren. Aḥraz ur yezmir ara ad yekkes awgelhen s tefyirt-a tuffirt: ttxil-k·m selken ma yella d tafyirt tuffirt tameɣtut i teskecmeḍ. Tuccḍa deg uzeṭṭa: ma ulac aɣilif senqed tuqqna-inek·inem syen ɛreḍ tikkelt-nniḍen. - Tiririt n uḥraz: Askazal n tsarut n tririt… Asali n tsura… @@ -1936,15 +1634,11 @@ %d tasarut tamaynut tettwarn ɣer tɣimit. %d tisura timaynutin ttwarnant ɣer tɣimit. - Tiririt n lqem akk aneggaru n tsura (%s) ur teddi ara. Awgelhan n tɣimit ur yettwarmed ara - - Aḥraz n tsarut yettusbadu akken iwata i tɣimit-a. Aḥraz n tsarut ur yermid ara i tɣimit-a. Tisura-inek·inem ur ttwaḥrazent ara seg tɣimit-a. - Aḥraz ɣer-s azmul seg tɣimit tarussint s usulay %s. Aḥraz ɣer-s azmul ameɣtu seg tɣimit-a. Aḥraz ɣer-s azmul ameɣtu seg tɣimit %s yettusneqden. @@ -1952,61 +1646,44 @@ Aḥraz ɣer-s azmul arameɣtu seg tɣimit yettusneqden %s Aḥraz ɣer-s azmul arameɣtu seg tɣimit ur yettusneqden ara %s Awway n telɣut yettwattkalen i uḥraz (%s) ur yeddi ara. - I useqdec n uḥraz n tsura deg tɣimit-a, err-d s tefyir-ik·im tuffirt neɣ s tsarut n tririt tura. Tukksa n uḥraz (%s) ur teddi ara - Asenqed n waddad n uḥraz Kkes tisura-inek·inem n uwgelhen yettwaḥerzen ɣef uqeddac\? Ur tettuɣaleḍ ara ad tizmireḍ ad tesqedceḍ tasarut-ik·im n tririt i tɣuri n umazray n yiznan yettwawgelhen. - Aḥraz n tsarut amaynut n yizen aɣelsan tettwaf-d. \n \nMa yella ur tesbaduḍ ara tarrayt n tririt tamaynut, amker yezmer ad yeɛreḍ ad yekcem ɣer umiḍan-ik·im. Snifel awal uffir n umiḍan-ik·im syen sbadu tarrayt n tririt tamaynut din din deg yiɣewwaren. Aḥraz aɣelsan Seḥbiber iman-ik·im mgal asruḥu n unekcum ɣer yiznann & yisefka yettwawgelhen - Tisura timaynutin n yizen aɣelsan Sefrek deg uḥraz n tsarut - Aḥraz n tsura-inek·inem. Aya yezmer ad yeṭṭef aṭas n tesdidin… - - Sbadu aḥraz aɣelsan - Aḥraz n tsarut %d… Aḥraz n tsura %d… - Iɣewwaren n uqeddac ummid awurman Element yufa-d tawila n uqeddac udmawan i taɣult usulay—inek·inem n uqeddac \"%1$s\": \n%2$s Seqdec tawila - Tettusuffɣeḍ ssebba n yinekcam arimeɣta neɣ yemmuten. - Senqed s userwes n uzrir ameẓẓyan n uḍris. Bdu asenqed Aselken n tɣimit-a ad yettucreḍ fell-as tettwattkal, yerna ad tettucreḍ ula d tiɣimit-ik·im tettwattkal i bab-is. - Selkem tiɣimit-a s usentem n yimujiten-a i d-yettbanen ɣef ugdil n baba-is Selkem tiɣimit-a s usentem n wuṭṭunen-a i d-yettbanen ɣef ugdil n baba-is - Tremseḍ-d asuter n uselken i d-iteddun… Aṛaǧu n usentem sɣur bab-is… - Teslekneḍ taxxamt-a akken iwata. Ulac acu i d-yettwabnen\? Mačči akkimsaɣen ssefraken aselken amyigew ar tura. Seqdec aselken. Seqdec aselken. - Tama-nniḍen tessefsax aselken. \n%s Aselken yettusefsax. \nTaɣzint: %s - Aselken amyigaw n tɣimit %s yebɣa ad issenqed tiɣimit-inek·inem - Aseqdac issefsax asenqed Akud n usenqed yemmed Tiɣimit ur teẓri ara ɣef tnigawt-a @@ -2018,9 +1695,7 @@ Ulac amṣada n useqdac Ur tesseqdaceḍ ara ula d yiwen n uqeddac n timagit Ulac aqeddac n timagit yettusiwlen, yettusra ad twennzeḍ awal-inek·inem uffir. - Yettban-d am wakken tettaɛraḍeḍ ad teqqneḍ ɣer uqeddac agejdan-nniḍen. Tebɣiḍ ad teffɣeḍ\? - Ttekki deg usarag s useqdec n usnas. Yuzen-ak·am-d tinubga Tettwafem akken ma tellam! @@ -2028,15 +1703,12 @@ Ansuf ɣer uxxam! Idiwenniyen-inek·inem n yizen usrid ad d-ttwaskanen da Tixxamin-inek·inem ad d-ttwaskanent da - Rnu asedmar Wali isedmaren Sken-d iznan yettwakksen Yettewekkes uneḍru sɣur aseqdac Aneḍru yellan s lmendad n unedbal n texxamt Aneggaru yettwaẓreg sɣer %1$s ɣef %2$s - - Aneḍru ur nemsil ara, ulamek ara d-yettwaskan Ulac azeṭṭa. Ma ulac aɣilif senqed tuqqna-inek·inem ɣer Internet. Ma ulac aɣilif ṛǧu… @@ -2045,44 +1717,32 @@ Taxxamt tettwarna, maca kra n tinubgiwin ur ttwaznent ara i teɣzint-a: \n \n%s - Tella-d tuccḍa deg wawway n telɣut yettwattkalen Tella-d tuccḍa deg wawway n yisefka n uḥraz n tsura - Kter tisura e2e seg ufaylu \"%1$s\". - Turagin n wis tlata Tesneqdeḍ yakan taxxamt-a! - Ulac ilugan n yilɣa yettusbadun Glem-d isniram-inek·inem da Tanemmirt, isumar ttwaznen akken iwata Tuzna n yisumar ur teddi ara (%s) - Awgelhen n utṛumbun… Awgelhen n ufaylu… Tuzna n ufaylu (%1$s / %2$s) - Asali n ufaylu %1$s… Afaylu %1$s yettusider-d! - Ur nezmir ara ad d-naf ayen i tettnadiḍ\? Rnu taxxamt tamaynut Azen izen usrid amaynut Ẓer akaram n texxamt - Ulac igmaḍ i yettwafen, seqdec Rnu s usulan n Matrix i unadi ɣef uqeddac. Bdu aru i wakken ad tesɛuḍ igmaḍ Sizdeg s yisem n useqdac neɣ s usulay… - Attekki deg texxamt… - Ẓer amazray i yettuẓergen - Senqed tiwtilin Ili-k tettwafeḍ sɣur wiyaḍ Seqdec abuḍen, tileggiyin, iwiǧiten d yikemmusen n yistikar - Swel aqeddac n timagit Aql-ak·akem akka tura tesseqdaceḍ %1$s i wakken ad d-tafeḍ, daɣen ad tettwafeḍ sɣur inermisen yellan i tessneḍ. Akka tura ur tesseqdaceḍ aqeddac n timagit. I wakken ad d-tafeḍ daɣen ad d-tettwafeḍ sɣur yinermisen yellan i tessneḍ, rnu yiwen ddaw. @@ -2099,19 +1759,15 @@ Timagit n uqeddac ulac ɣer-s tiwtilin n yimeẓla Izen n uḍris yettwazen ɣer %s. Ttxil-k·m sekcem tangalt n uselken yellan deg-s. Tangalt n uselken d tarameɣtut. - Tura akka tebdiḍ tansiwin n yimayl neɣ uṭṭunen n tiliɣri ɣef uqeddac n timagit %1$s. Tesriḍ ad talseḍ tuqqna ɣer %2$s i useḥbes n beṭṭu-nsen. Qbel tiwtilin n umeẓlu n uqeddac n timagit (%s) i wakken ad tsirgeḍ iman-ik·im ad d-tettwafeḍ s yimayl neɣ s wuṭṭun n tiliɣri. - Azen taceqquft yeddan - Ldi umuɣ n tunigin Ldi umuɣ n tmerna n texxamin Mdel umuɣ n tmerna n texxamin… Rnu adiwenni usrid amaynut Rnu taxxamt tamaynut Ɛeddi ɣer ukessar n usebter - Azen aqbur-a Agbur-a yettwakter-d. \n @@ -2122,19 +1778,15 @@ Agbur-a yettwakter-d mačči d win i iwulmen. \n \nMa yella dayen ur tebɣiḍ ara ad twaliḍ agbur-nniḍen sɣur aseqdac-a, tzemreḍ ad t-tesweḥleḍ i wakken ad teffreḍ iznan-ines - Element yesra tasiregt i usekles n tsura-inek·inem E2E ɣef uḍebsi. \n \nMa ulac aɣilif sireg anekcum ɣef yisfuyla udhimen i d-iteddun i wakken ad tizmireḍ ad tsifḍeḍ tisura-ik·im s ufus. - Ulac akk tuqqna n uzeṭṭa i igerrzen akka tura - Yuzen iznen i d-yettunefken d arewway Arewway Rnu ɣer yimelyan n yimdanen baṭel ɣef uqeddac azayez ameqqran akk Tanezduɣt n Premium i tkebbaniyin Iɣewwaren udmawanen & leqqayen - Qqen ɣer yimeẓla n Element Matrix Qqen aqeddac udmawan Tanezduɣt n Premium i tkebbaniyin @@ -2148,11 +1800,9 @@ Asnas ur yezmir ara ad yernu amiḍan ɣef uqeddac-a agejdan. \n \nTebɣiḍ ad tjerrdeḍ s useqdec n umsaɣ web\? - Awal-ik·im uffir mazal ar tura ur yettusenfel ara. \n \nSeḥbes aseddu n usnifel\? - Sbadu imayl i wakken ad d-terreḍ amiḍan-ik·im. Ticki, tzemreḍ s wudem afrayan ad tsirgeḍ imdanen i tessneḍ ad ak·akem-afen s yimayl-inek·inem. Sbadu uṭṭun n tiliɣri s wudem afrayan ad tsirgeḍ imdanen i tessneḍ ad ak·akem-afen. Ma ulac aɣilif seqdec amasal agreɣlan. @@ -2160,28 +1810,23 @@ Ma ulac aɣilif seqdec amasal agreɣlan (uṭṭun n tiliɣri ilaq ad yebdu s \'+\') Uṭṭun n tiliɣri agreɣlan ilaq ad yebdu s \'+\' Uṭṭun n tiliɣri yettban-d d arameɣtu. Ma ulac aɣilif senqed-it - Amiḍan-ik·im mazal ur yettwarna ara ar tura. \n \nSeḥbes akala n usekles\? - Aql-aɣ akken nuzen imayl ɣer %1$s. \nMa ulac aɣilif sit ɣef useɣwen i yellan deg-s i wakken ad tkemmleḍ timerna. Tangalt yettwaskecmen d tarameɣtut. Ma ulac aɣilif senqed. Aqeddac agejdan d aqbur Aqeddac-a agejdan isselkam lqem aqbur maḍi i tuqqna ɣer-s. Suter anedbal n uqeddac-ik·im aqejden ad t-tleqqemḍ. - Aṭas n yisutar i yettwaznen. Tzemreḍ ad tɛerḍeḍ ticki deg %1$d tasint… Aṭas n yisutar i yettwaznen. Tzemreḍ ad tɛerḍeḍ ticki deg %1$d tsinin… - Neɣ ma ulac, ma yella tesɛiḍ yakan amiḍan yerna tessneḍ inekcam-inek·inem n Matrix d wawal-inek·inem uffir, tzemreḍ ad tesqedceḍ tarrayt-a: Ma yella tesbaduḍ amiḍan ɣef uqeddac agejdan, seqdec asulay-inek·inem n Matrix (am. @user:domain.com) d wawal uffir ddaw. Ma yella ur tecfiḍ ara ɣef wawal-ik·im uffir, uɣal ɣer deffir ad t-twennzeḍ. Wagi mačči d identifier n useqdac ameɣtu. Amasal deg-s ccekk: \'@user:homeserver.org\' D awezɣi ad d-naf aqeddac agejdan ameɣtu. Ma ulac aɣilif senqed inekcam-inek·inem - Yezmer ad yili seg waṭas n ssebbat: \n \n• Tbeddleḍ awal-ik·im uffir deg tɣimit-nniḍen. @@ -2198,34 +1843,25 @@ \nKcem tikkelt-nniḍen i wakken ad tkecmeḍ ɣer yisefka d yiznan n umiḍan-inek·inem. Aseɣwen-inek·inem n Matrix.to ur yemsil ara akken iwata Ala igmaḍ imezwura i d-yettwaseknen, aru ugar n yisekkilen… - Element yezmer ad yewḥel ugar n tikkal mi ara d-tili tuccḍa ur nettwaṛǧa ara - Taɣult n yimayl—ik·im ur tesɛi ara azref i wakken ad tettwasekles ɣef uqeddac-a - Tuqqna ur nettwattkal ara Senqed aseqdac-a s usentem n yimujit-a asuf i d-yettbanen ɣef ugdil-ines, deg yiwem umsizwer. I tɣellist meqqren, seqdec ttawilat-nniḍen yettwattkalen n teywalt neɣ eg aya s timmad-ik·im. Muqel aɣar azegzaw i wakken ad tḍemneḍ aseqdac yettwattkalen. Ttkel ɣef meṛṛa iseqdacen yellan deg texxamt i wakken ad tḍemneḍ taxxamt d taɣelsant. - Yiwen seg wayen i d-iteddun yezmer ad yettwaker: \n \n- Aqeddac-ik·im agejdan \n- Aqeddac agejdan wuɣur yeqqen useqdac tessenqadeḍ \n- Tuqqna-inek·inem n internet neɣ tin n useqdac-nniḍen \n- Ibenk-inek·inem neɣ win n useqdac-nniḍen - Freḍ tangalt d yibenk n useqdac-nniḍen i wakken ad tesneqdeḍ yal yiwen s wudem aɣelsan Ulamek yettwafreḍ Ma yella mačči d kečč·kemm s timmad-ik·im, serwes imujit deg ubdil - Selken s userwes n yimujiten - Senqed s yimujit Ma yella ur tezmireḍ ara ad tferḍeḍ tangalt nnig, senqed s userwes n tegrumma tamecṭuḥt, tafrayant n yimujiten. - Tugna n tengalt QR - Senqed %s Yettusenqed %s I tɣelliset akk i ifazen, senqed %s s usenqed n tengalt n useqdec asuf ɣef isin yibenkan-inek·inem. @@ -2241,32 +1877,24 @@ %1$d yimdanen Tuffɣa seg texxamt… - Imaẓragen Anedbal deg %1$s D amaẓrag deg %1$s Amezwer deg %1$s D udmawan (%1$d) deg %2$s - "Element ur isekker ara ineḍruyen n wanaw \'%1$s\'" "Element ur isekker ara izen n wanaw \'%1$s\'" Element yemlal-d ugur mi ara d-yettarra agbur n uneḍru s usulay \'%1$s\' - Tiɣimit-a ulamek ara tebḍu aselken-a akked tqimiyin-nniḍen. \nAselken ad yettwaseklas s wudem adigan syen yettwabḍu deg lqem i d-iteddun n usnas. - Tixxamin n melmi kan Tixxamin-nniḍen - Yuzen iznan i d-yettunefken yeɣma s yiniten am teslit n Unẓar Yuzen tasedmirt i d-yettunefken teɣma s yiniten am teslit n Unẓar - Amaẓrag n yizen - Akken ara tremdeḍ awgelhen i texxamt, ur yettizmir ara ad yettwakkes. Iznan n texxamt yettwaznendeg texxamt yettwawgelhen ur ten-yettwali ara uqeddac, ala wid yettekkan deg texxamt. Armad n uwgelhen ur yettaǧǧa ara kra n yiṛubuten d kra n tleggiyin ad ddun akken iwata.Issin ugar ɣef uwgelhen. I wakken ad tḍemneḍ taɣellist-ik·im, senqed %s s userwes n tenqalt n useqdec asuf. I wakken ad tḍemneḍ taɣellistik·im, eg ayagi s timmad-ik·im neɣ seqdec abrid n teywalt iɣef ara tettekleḍ. - Serwes imujit ufrin, s uḍman ad d-banen deg yiwen usemizwer. Serwes tangalt d win i d-yettwaskanen ɣef ugdil n useqdac-nniḍen. Iznan akked useqdac-a ttwawgelhen seg yixef ɣer yixef yerna ur yezmir wis tlata ad ten-iɣer. @@ -2279,40 +1907,28 @@ Azmul anmidag yettwarmed. \nTisura ur ttwattkalent ara Azmul anmidag ur yettwarmed ara - Tɣimiyin turmidin Sken meṛṛa tiɣimiyin Sefrek tiɣimiyin Ffeɣ seg tɣimit-a - Ulac talɣut n uwgelhen i yellan - Tiɣimit-a tettwattkal i yiznan iɣelsanen acku tesneqdeḍ-tt: Senqed tiɣimit-a i wakken ad tt-tcerḍeḍ tettwattkal & anef-as ad tekcem ɣer yiznan yettwawgelhen. Ma yella ur teqqineḍ ara ɣer tɣimit-a, amiḍan-inek·inem yezmer ad yettwaker: - %d tɣimit t ururmidt %d tɣimiyin turmidin - Yemmed s wudem aɣelsan - Seqdec tiɣimit i yellan i wakken ad tesneqdeḍ tagi, s umuddu n uzref i wakken ad tekcem ɣer yiznan yettwawgelhen. - - Awway n tɣimiyin ur yeddi ara Tiɣimit-a tettwattkal i yiznan iɣelsanen acku %1$s (%2$s) issenqed-itt: %1$s (%2$s) yettuzmel deg useqdec n tɣimit tamaynut: Imi mazal useqdac-a ur yettkil ara ɣef tɣimit-a, iznan yettwaznen seg-s d wid i d-yettwaznen qer-s ad sɛun tacreḍt n lemḥadra. Neɣ ma ulac, tzemreḍ ad tent-tesneqdeḍ s ufus. - - Wennez azmul anmidag Tangalt QR - Qrib ad tawḍeḍ! Ma yella %s kifkif aɣar i d-yeskanay\? Tuqqna ɣer uqeddac truḥ Askar n usafag yermed - Ifecka n tneflit %d tafrant @@ -2325,34 +1941,26 @@ Yerna assenqed afessas Seqdec tafyirt tuffirt n tririt neɣ tasarut Ma yella ur tezmireḍ ara ad tkecmeḍ ɣer tɣimit i yellan - Ur nessaweḍ ara ad naf tuffirin deg uklas Ilaq ad tkecmeḍ ɣer uklas uffir ala seg yibenk yetwaḍemnen - Kkes… Tebqiḍ ad tazneḍ taceqquft-a yaddan i %1$s\? Azen tugna s teɣzi taneẓlit Azen tuniwin s teɣzi taneẓlit - Rnu taɣzint Taɣzint n tukksa - Yettewekkes uneḍru sɣur aseqdac, taɣzint: %1$s Aneḍru yella-d s lmendad n unedbal n texxamt, taɣzint: %1$s - Serreḥ i umazray n yiznan yettwawgelhen - Aru i usenqed d uselken Seqdec tiɣimit-a i usenqed tiɣimit-ik·im tamaynut, ayen ara tt-yeǧǧen ad tekcem ɣer yiznan yettwawgelhen. Mačči d nekk Amiḍan-ik·im yezmer ad yettwaker - Ma yella tesfesxeḍ, ur tettizmireḍ ara ad teɣreḍ iznan yettwawgelhen ɣef yibenk-a, ula d iseqdacen-nniḍen ur t-ttamnen ara Ma yella tesfesxeḍ, ur tettizmireḍ ara ad teɣreḍ iznan yettwawgelhen ɣef yibenk-inek·inem amaynut, ula d iseqdacen-nniḍen ur t-ttamnen ara Ur tesneqdeḍ ara %1$s (%2$s) ma yella ad tesfesxeḍ tura. Bdu tikkelt-a deg umaɣun-ines n useqdac. - Yiwen seg wayen i d-iteddun yezmer ad yettwaker: \n \n- Awal-ik·im uffir @@ -2361,48 +1969,34 @@ \n- Tuqqna ɣer internet yettuseqdacen seg yal ibenk \n \nAd ak·akem-nwelleh ad tesnifleḍ awal-ik·im uffir & tsarut n tririt deg yiɣewwaren tura tura. - Senqed ibenkan-ik·im seg yiɣewwaren. Yettwasefsex usenqed - Tefyirt tuffirt n tririt Tasarut n yizen Awal uffir n umiḍan - Sbadu %s Sirew tasarut n yizen - Sentem %s - Sekcem %s inek·inem i wakken ad tkemmleḍ. - Ḍmen & ldi iznan yettwawgelhen syen ttkel s %s. Sekcem %s inek·inem i usentem-ines. Ur sseqdac ara awal-ik·im uffir n umiḍan. - Sekcem tafyirt n tɣellist ara tissineḍ kan keččini·kemmini, tettuseqdac i wakken ad teḍmen tuffriwin deg uqeddac-ik·im. - Asbadu n tefyirt tuffirt n tririt ad ak·am-teḍmen taɣellist & tawaledyawt n yiznan yettwawgelhen, yettwattkalen. Ma yella teffɣeḍ tura, yezmer ad ak·am-ruḥen yiznan yettwawgelhen d yisefka ma yella tesruḥeḍ anekcum ɣer yinekcam-inek·inem. \n \nTzemreḍ ad tesbaduḍ aḥraz aɣelsan rnu ad tesferkeḍ tisura-inek·inem melmi i tebɣiḍ deg yiɣewwaren. - Iznan deg texxamt-a ttwawgelhen seg yixef ɣer yixef. Issin ugar & senqed iseqdacen deg yimuɣna-nsen. Awgelhen yettusqedcen deg texxamt-a ur yettusefrak ara - %s yerna taxxamt syen iswel-itt. Aql-ak·akem terniḍ, tsewleḍ taxxamt. - Qrib ad tawḍeḍ! Wissen ma yella ibenk-nniḍen kifkif aɣar i d-yeskanay\? Qrib ad tawḍeḍ! Deg uṛaǧu n usentem… Aktar n tsura ur yeddi ara - Aswel n yilɣa Sbadu azal n wulɣu s uneḍru - Isem n useqdac d/neɣ awal uffir d arameɣtu. Awal uffir yettwaskecmen yebda neɣ yekfa s tallunt, ma ulac aɣilif senqed-it. Izen… - Rmed azmul anmidag Sekcem %s inek·inem i wakken ad tkemmleḍ Tefyirt tuffirt n tririt @@ -2415,10 +2009,8 @@ seqdec tasarut-ik·im n tririt n uḥraz n tsarut Ur tessineḍ ara tafyirt-ik·im tuffirt n uḥraz n tsarut, tzemreḍ %s. Tasarut n tririt n uḥraz n tsarut - Sewḥel tuṭṭfiwin n ugdil n usnas Armad n uɣewwar-a ad yernu FLAG_SECURE ɣer meṛṛa irmad. Ales asenker n usnas i wakken ad yemmed usnifel. - Afaylu n umidyat yettwarna ɣer temsikent D awezɣi ad yernu ufaylu n umidyat ɣer temsikent Seqdec lqem akk aneggaru n Element ɣef yibenkan-inek·inem-nniḍen: Element Web, Element n tnarit, Element iOS, Element i Android neɣ amsaɣ-nniḍen n Matrix yessefraken azmul anmidag @@ -2426,12 +2018,10 @@ Senqed amyigew s yimujit Sentem timagit-inek·inem s usenqed n yinekcam-a, anef-as ad yekcem ɣer yiznan yettwawgelhen. Suref-aɣ, tamahelt-a ulamek i tedda akka tura i yimiḍanen i yettwaqqnen s useqdec n unekcum asuf. - Senqed tikkelt-nniḍen aseɣwen-a Aseɣwen %1$s ad ak·akem-yawi ɣer usmel-nniḍen: %2$s. \n \nTebɣiḍ s tidet ad tkemmleḍ\? - Ffeɣ seg tuqqna n uqeddac n timagit %s\? Aqeddac-a n timagit iɛedda d aqbur. Element yessafrak kan API V2. Tamahekt-a ulamek tedda. Aqeddac agejdan d aqbur. @@ -2440,15 +2030,12 @@ I tɣellist n tbaḍnit-ik·im, Element yessefrak kan tuzna n yimaylen d wuṭṭunen n tiliɣri yettudwin i useqdac. Assaɣ ur yeddi ara. Akka tura ulac akk assaɣ d unekcam-a. - Aqeddac-ik·im agejdan (%1$s) yefka-d takti n useqdec n %2$s d aqeddac-ik·im n timagit Neɣ ma ulac, tzemreḍ ad teskecmeḍ URl n uqeddac n timagit i tebɣiḍn Sekcem URL i uqeddac n timagit Sekcem tafyirt n tɣellist ara tissineḍ kan kečč·kemm, syen sirew tasarut i uḥraz. - Sekcem tafyirt n tɣellist ara tissineḍ kan keččini·kemmini, tettuseqdac i wakken ad teḍmen tuffriwin deg uqeddac-ik·im. Sekcem tafyirt-inek·inem n tɣellist tikkelt-nniḍen i usentem-ines. - Araǧu n izen-a, aya yezmer ad yeṭṭef akud Ur tezmireḍ ara ad teldiḍ taxxamt ansi i d-tettwagedleḍ. Ur nessaweḍ ara ad d-naf taxamt-a. Muqel ma tella d tidet. @@ -2457,20 +2044,15 @@ Tamahelt-a tesra asentem-nniḍen. \nI ukemmel, ma ulac aɣilif sekcem awal-ik·im uffir. %s yettaɛraḍ ad d-isali tazmilt tufrint deg tesnakudt n texxamt-a, maca ur yessaweḍ ara ad tt-naf. - Neɣ; dmen aḥrazen-inek·inem s tefyirt tuffirt n uɛeddi, yettwaskelsen deg wadeg aɣelsan. Tiririt n lqem n uḥraz… Rnu iccer ara yettunefken i yilɣa ur nettwaɣra ara deg ugdil agejdan. - Rmed iɣmisen ɣezzifen. Ma ulac aɣilif ɛreḍ tikkelt-nniḍen mi ara tqebleḍ tiwtilin n uqeddac-ik·im agejdan. - Mdel aɣarrac n uḥraz n tsura Mačči d ayen ilaqen Yettwazen d ayen ur nlaq ara Seɣzef asiti ɣef texxamt i wakken ad twaliḍ ugar n textiṛiyin - - Semṣer, rnu sagen tarmit-ik·im "Am yimaylen, imiḍanen sɛan kan yiwen n uqeddac agejdan, ɣas ma tzemreḍ ad temmeslayeḍ i yal yiwen" Ma ulac aɣilif sɛeddi akayad captcha @@ -2480,12 +2062,10 @@ Huzz tiliɣri-inek·inem i wakken ad teskeydeḍ talast n tifin Asenker n tuqqna deg wakud ilaw ur yeddi ara. \nMa ulac aɣilif suter deg unebdal n uqeddac-iim agejdan ad yeswel aqeddac TURN i wakken ad qeɛden isawalen. - Ma yella anedbal n uqeddac yenna-d belli aya yettuau, ẓer ma yella adsil umḍin ddaw yemṣada d udsil umḍin i d-mudden nutni. Aselken yettubeddel deg ubdil n win yettwamanen deg tiliɣri-inek·inem. Aya MAČČI D AYEN IGERRZEN. Issefk UR TETTAQBALEḌ ARA aselkin-a amaynut. Aselkin yettwabeddel seg win yettwamanen ɣer win ur nettwaman ara. Ahat aqeddac iɛawed-d aselkin-ines. Nermes anedbal n uqeddac ɣef udsil umḍin yetturaǧun. Ur qebbel ara aselkin alamma isuffeɣ-d unedbal n uqeddac adsil umḍin yemṣadan d win yellan ddaw-a. - [%1$s] \nTuccḍa yekka nnig tezmert n Element, akken i d-yenna Google, tuccḍa-a teskan-d belli ibenk ɣer-s aqettun n yisnasen yettwaskelsen s FCM. Tuccḍa ur d-tettili ara ala ma yilin umiḍan n yisnasen aṭas, ɣef waya ur ilaq ara ad tḥaz aseqdac n tlemmast. [%1$s] @@ -2499,12 +2079,10 @@ \nImsefrak n yimsidaf temmsen-d isefka n twila, syen zemren ad snilen iwiǧiten, ad aznen tinubgiwin ɣer teamin yerna ad sbadun iswiren n tezmert s yisem-ik·im. Msel iznan s useqdec n tseddast n markdown send ad ttwaznen. Aya ad isireg amsal leqqayen am useqdec n yizamulen n yitran i uskan n uḍris uknan. Taqeffalt Kcem n unasiw n useɣzan ad tazen izen ideg ara teg angaz gar yizirigen - Element yezmer ad yeddu deg ugilal i usefrek n yilɣa-inek·inem s wudem aɣelsan, uslig. Aya yezmer ad iḥaz aseqdec n uẓru. Element yesra ad yeǧǧ tuqqna s usemdu meẓẓiyen ɣef ugilal i wakken ad d-yawi ilɣa yettwamanen. \nƔef ugdil i d-iteddun, ad tettusnubegteḍ i wakken ad tmuddeḍ tisirag i Element ad yeddu i lebda ɣef ugilal, ttxil-k·m qbel. Askar n usekles n yisefka yessemras imsizdeg afrayan i wakken ileqman n tihawt d yilɣa n tira ad ttwasizedgen. - Tigi d timahilin tarmitanin i izemren ad rẓent s wayen ur nettwaṛǧa ara. Seqdec-itent maca ɣur-k·m. Aya ad yerr amiḍan-ik·im ur yettusexdam ara i lebda. Ur tettizmireḍ ara ad tkecmeḍ, ula d amdan-nniḍen ur yettizmir ara ad yales ajerred s usulay-a n useqdac. Aya ad isuffeɣ amiḍan-ik·im seg meṛṛa tixxamin ideg ittekka, yerna ad yekkes akk talqayt n umiḍan-ik·im seg uqeddac n timagit. Ulac tuɣalin ɣer deffir deg tigawt-a. \n @@ -2513,7 +2091,6 @@ \nAbani n yiznan deg Matrix am tin n yimaylen. Tatut-nneɣ n yiznan-inek·inem anamek-is, iznan i tuzneḍ ur ttwabḍun ara ula d yiwen n useqdac amaynut neɣ ur nettwasekles ara, maca iseqdacen yettwaskelsen i yesɛan anekcum ɣer yiznan-a mazal ad sɛun anekcum ɣer unɣal-nsen. Asnerni n temlellit s usali n yiɛeggalen n texxamt kan lawan tmeẓriwt tamezwarut. Aqeddac-ik·im agejdan ur yessefrak ara asali ẓẓayen n yiɛegggalen n texxamt akka tura. Ɛreḍ ticki. - Ad nekles anɣal yettwawgelhen n tsura-inek·inem ɣef uqeddac-ik·im agejdan. Mmesten aḥraz-inek·inem s tefyirt tuffirt i wakken ad yeqqim d aɣelsan. \n \nI tɣellist tafellayt, ilaq ad yemgarad ɣef wawal ufiir n umiḍan-ik·im. @@ -2522,32 +2099,129 @@ Tiɣimit ur tessaweḍ ara ad teqbel amtawi n tsarut, agbar, MAC neɣ tarrayt SAS Af-d iznan ur nettwaɣra ara da Taskant n texxamt ara yettwaɣran deg umaḍal ur tettusefrak ara ar tura deg Element - Ulac tinezgarin push ikelsen - Tuzna n tenfult (%1$s / %2$s) Rmed afraḍ i tririt deg tesnakudt Aqeddac n timagit i tferneḍ ulac ɣer-s akk tiwtilin n yimeẓla. Ur ttkemmil ara ala ma yella tettekleḍ ɣef umeẓlu Iɣmisen ɣezzifen ad ɛawnen ineflayen s umuddu n wugar n yiɣemisen mi ara tazneḍ aneqqis RageShake, ula ma yili yermed asnas ur yettazen ara agbur n yiznan neɣ isefka-nniḍen usligen. - - Akka d-yettban aqeddac yettaṭṭaf aṭas n wakud ɣef tririt. Yezmer aya yekka-d seg yir tuqqna neɣ seg tuccḍa deg uqeddac. Ma ulac aɣilif ɛreḍ tikkelt-nniḍen ticki. - Tiɣimit-a tamirant n useqdac %1$s ma d kečč·kemm ad tesnetmeḍ inekcam i useqdac %2$s. Aya ur t-yessefrak ara Element. \nMa ulac aɣilif, deg tazwara sfeḍ isefka, syen kcem tikkelt-nniḍen s umiḍan-nniḍen. - Askar n uneflay yermed timahilin i yeffren yerna yezmer daɣen ad yerr asnas ur yerkid ara akken iwata. I yineflayen kan! Abrir arurad %d n tsint %d n tsintin - Sken tidyanin n waddad n uɛeggal n texxamt Tiqeffalin n uṛubut Taggrayt n usenqed - Aseɣwen ur yemsil ara akken iwata Ur tesɛiḍ ara tasiregt ad tebduḍ asiwel deg texxamt-a Issedmer s: %s - + Sekyed Push + Anadi deg texxamin yettwawgelhen ur yettusefrak ara akka tura. + Sizdeg iseqdacen yettwagedlen + Mudd tisirag i unekcum ɣer yinermisen-inek;inem. + I usmiḍen n tengalt QR, tesriḍ ad tsirgeḍ anekcum ɣer tkamiṛat. + Azen azray n yisutar n beṭṭu n tsura + Ulac akkigmaḍ + Ur suffuɣ ara + Rnu + Ur tesεiḍ ara azref ad tesiwleḍ + Ur tesεiḍ ara azref ad tebduḍ asarag s tilifun + Bdu asqerdec + Wennez + Rmed abyumitri + Swel ammesten + Mmesten anekcum s useqdec n PIN d ubyumtri. + Mazal ur tettwarna ara texxamt ar tura. Sefsex timerna n texxamt\? + Tangalt QR d tarameɣtut (URI d arameɣtu)! + Senfel PIN inek·inem amiran + Tangalt PIN tettusra yal mi ara teldiḍ Element. + Llan yisenfal ur nettusekles ara. Sefsex isenfal\? + Sbadu avaṭar + Aseɣwen n Matrix + Asentel: + Terniḍ. + Rnu tugna seg + PIN yettusra seld 2 tesdatin + Nadi inermisen deg Matrix + Suffeɣ-d tansa-a + Suffeɣ-d tansa \"%1$s\"\? + Suffeɣ-d tansa tamaynut s ufus + Tagi d tansa tagejdant + Tansiwin n texxamt + Anekcum n texxamt + Ulɣu yettwasit fell-as! + Askan n wulɣu + Twalaḍ alɣu! Sit-iyi fell-as! + Tella tuccḍa deg urmas n push. Tifrat i iwulmen d allus n usebded n usnas. + Asnas irmes-d PUSH + Assenqed + Tansiwin n texxamt + %1$d ɣef %2$d + Publier + Asentel + Melmi kan + Sefsex ibeddilen + Ttxil-k·m mudd-d tansa n texxamt + Taxxamt-a ur tesɛi ara tansiwin tidiganin + Sken talqayt + Tangalt QR + Iɣewwaṛen n texxamt + Tansa n texxamt + Mmesten anekcum + Smiḍen tangalt QR + Tansa tamynut i d-yettusuffɣen (am. #alias:server) + Isumar + 🔐️ Rnu-d ɣur-i ɣer element + Tangalt PIN d nettat kan i d ttawil s wayes ara teldiḍ Element. + Rnu asentel + Snubget-d imeddukkal + Tangalt-inu + Ma yella twennzeḍ kullec + Ur tezmireḍ ara DM iman-ik·im! + Ur d-suffuɣ ara tansa-a + %1$s aked %2$s + Sken agbur deg yilɣa + Bḍu s uḍris + Tansiwin tizuyaz + Tansiwin tidiganin + Isnifal n unekcum ɣer umazray ad ddun deg yiznan i d-iteddun deg texxamt-a. Timeẓriwt n umazray yellan ur yettbeddil ara. + Tansa-a ha-tt-an yakan deg useqdec + Rnu imdanen + Ffeɣ + Tansiwin i d-yettusuffɣen ur yezmir ula d yiwen ad tent-isseqdec ɣef yiqeddacen akk i wakken ad yekcem ɣer texxamt-ik·im. I wakken ad tsuffɣeḍ tansa, ilaq ad tettusbadu deg tazwara d tansa tadigant. + Isem n texxamt + Ffer talqayt + Timerna n texamt… + Iɣewwaren + Snifel Pin + Izen uslig + Inermisen + Tgiḍ aya i tinubga kan. + Iznan deg texxamt-a ttwawgelhen seg yixef ɣer yixef. + Wennez kullec + Yettwarna s tengalt QR + Rnu tansa tadigant + Ilaq ad tesremdeḍ aya ma yella taxxamt ad tettwaseqdec kan i uttekki d trebbaɛ tigensanin ɣef uqeddac-ik·im agejdan. Ayagi ur yettubeddal ara ɣer sdat. + + %d tinubga + %d n tnubgiwin + + Tangalt PIN tettusra seld 2 tesdatin n war aseqdec n Element. + Iznan dagi ur ttwawgelhen ara seg yixef ɣer yixef + Tangalt QR ur tettusmiḍen ara! + Bḍu tangalt-inu + Asnas yettṛaǧu PUSH + Kkes tansa \"%1$s\"\? + Tansiwin-nniḍen i d-yeffɣen: + %1$s deg %2$s d %3$s + Tansa tagejdant + + Sken ibenkani swayes i tzemreḍ ad tesneqdeḍ tura + Sken %d ibenkani swayes i tzemreḍ ad tesneqdeḍ tura + + Rnu adiwenni usrid amaynut s usulay n Matrix + \ No newline at end of file diff --git a/vector/src/main/res/values-nb-rNO/strings.xml b/vector/src/main/res/values-nb-rNO/strings.xml index c6275dd936..34c6134bff 100644 --- a/vector/src/main/res/values-nb-rNO/strings.xml +++ b/vector/src/main/res/values-nb-rNO/strings.xml @@ -112,15 +112,15 @@ Avvis Synkroniserer … - 1sek - %dsek + %ds + %ds - 1m + %dm %dm - 1t + %dt %dt @@ -394,7 +394,7 @@ Identitetstjener: Samtaler - 1 medlem + %d medlem %d medlemmer 1 medlem @@ -403,7 +403,7 @@ Søk Filtrer rommets medlemmer - 1 rom + %d rom %d rom Alle meldinger @@ -671,7 +671,7 @@ Vil du avbryte opplastingen\? Rommets navn - 1 aktivt medlem + %d aktivt medlem %d aktive medlemmer Forlat rommet @@ -691,12 +691,12 @@ %1$s, %2$s og andre skriver … Avbryt alle - 1 ny melding + %d ny melding %d nye meldinger Romdetaljer - 1 valgt + %d valgt %d valgte INVITERT @@ -889,7 +889,7 @@ Klarte ikke registrere bruker: Nettverksfeil Klarte ikke logge inn Klarte ikke logge inn: Nettverksfeil - Vennligst les og aksepter reglene for denne hjemmetjeneren: + Vennligst gjennomgå og godta retningslinjene til denne hjemmeserveren: Passordet ditt har blitt tilbakestilt. \n \nAlle øktene dine har blitt logget ut og får ikke lenger push-notifikasjoner. For å skru på notifikasjoner igjen, logg inn på enhetene på nytt. @@ -908,9 +908,269 @@ Vennligst be administratoren for hjemmetjeneren din (%1$s) til å sette opp en TURN tjener for at telefonsamtaler skal fungere ordentlig. \n \nAlternativt kan du prøve å bruke den offentlige tjeneren på %2$s, men dette vil ikke være like stabilt, og det vil dele IP-adressen din med den serveren. Du kan styre dette i instillinger. - e-postlenken har ikke blitt trykket på enda + E-postkoblingen som ikke er klikket på ennå Dette brukernavnet er allerede brukt Inneholdt ikke gyldig JSON Ugyldig JSON - Biletten din ble ikke gjenkjent + Angitt tilgangstoken ble ikke gjenkjent + Sikkerhetsfrase + Lagre din sikkerhetsnøkkel + Oppbevar sikkerhetsnøkkelen din et trygt sted, for eksempel en passordbehandling eller en safe. + Du endret rominnstillingene + Sett avatar + Du får ikke tilgang til denne meldingen + Venter på denne meldingen, dette kan ta en stund + På grunn av end-to-end-kryptering, kan det hende du må vente på at noens melding kommer, fordi krypteringsnøklene ikke ble sendt riktig til deg. + Du får ikke tilgang til denne meldingen fordi du har blitt blokkert av avsenderen + Du får ikke tilgang til denne meldingen fordi økten ikke er klarert av avsenderen + Du får ikke tilgang til denne meldingen fordi avsenderen med vilje ikke sendte nøklene + Venter på krypteringshistorikk + Riot er nå Element! + Vi er glade for å kunngjøre at vi har byttet navn! Appen din er oppdatert, og du er logget på kontoen din. + element + Lagre gjenopprettingsnøkkel i + Henter kontaktene dine… + Kontaktboken din er tom + Kontaktbok + Søk etter kontakter på Matrix + Push-varsler er deaktivert + Gjennomgå innstillingene dine for å aktivere push-varsler + + Feil kode, %d gjenværende forsøk + Feil kode, %d gjenværende forsøk + + Advarsel! Siste gjenværende forsøk før avlogging! + For mange feil, du er logget ut + Velg en PIN-kode for sikkerhet + Kunne ikke validere PIN-koden. Trykk på en ny. + Tilbakestill PIN + Ny PIN-kode + For å tilbakestille PIN-koden din, må du logge på igjen og opprette en ny. + Beskytt tilgangen + Beskytt tilgangen ved hjelp av PIN og biometri. + Konfigurer beskyttelse + Hvis du vil tilbakestille PIN-koden, trykker du på Glemt PIN-kode for å logge av og tilbakestille. + Aktiver biometri + Aktiver enhetsspesifikk biometri, som fingeravtrykk og ansiktsgjenkjenning. + PIN-kode er den eneste måten å låse opp Element. + Vis innhold i varsler + Vis detaljer som romnavn og meldingsinnhold. + Vis bare antall uleste meldinger i et enkelt varsel. + Krev PIN etter 2 minutter + PIN-kode kreves etter 2 minutter uten bruk av Element. + PIN-kode kreves hver gang du åpner Element. + Endre PIN-kode + Endre din nåværende PIN-kode + Bekreft PIN for å deaktivere PIN + Kan ikke åpne et rom der du er utestengt. + Finner ikke dette rommet. Forsikre deg om at den eksisterer. + Kan ikke DM deg selv! + Ugyldig QR-kode (Ugyldig URI)! + QR-kode ikke skannet! + Rommet er ennå ikke opprettet. Avbryte romopprettelsen\? + Det er ikke lagrede endringer. Forkast endringene\? + Forkaste endringer + Les kvitteringsliste + Be om krypteringsnøkler fra andre økter. + URL må starte med http[s]:// + Du ser på varselet! Klikk på meg! + Kunne ikke motta push. Løsningen kan være å installere applikasjonen på nytt. + Legg til konto + [%1$s] +\nDenne feilen er utenfor kontroll av Element. Det er ingen Google-konto på telefonen. Åpne kontoadministratoren og legg til en Google-konto. + Fiks Play Services + Element bruker Google Play Services for å levere push-meldinger, men det ser ikke ut til å være konfigurert riktig: +\n%1$s + Google Play Services APK er tilgjengelig og oppdatert. + Sjekk innstillinger + Kunne ikke laste tilpassede regler, prøv på nytt. + Noen varsler er deaktivert i dine tilpassede innstillinger. + Legg merke til at enkelte meldinger er satt til å være lydløse (gir et varsel uten lyd). + Egendefinerte innstillinger. + Varsler er ikke aktivert for denne økten. +\nKontroller Elementinnstillingene. + Varsler er aktivert for denne økten. + Sesjonsinnstillinger. + Varsler er deaktivert for kontoen din. +\nKontroller kontoinnstillingene. + Varsler er aktivert for kontoen din. + Varsler er deaktivert i systeminnstillingene. +\nKontroller systeminnstillingene. + Varsler er aktivert i systeminnstillingene. + En eller flere tester mislyktes. Send inn en feilrapport for å hjelpe oss med å undersøke. + En eller flere tester mislyktes, prøv foreslåtte løsninger. + Grunnleggende diagnostikk er OK. Hvis du fremdeles ikke mottar varsler, kan du sende inn en feilrapport for å hjelpe oss med å undersøke. + Kjører… (%1$d of %2$d) + Kjør tester + Feilsøking av diagnostikk + Feilsøk varsler + Personvern om varsler + Meldings betydning etter hendelse + Forsikre deg om at du har klikket på lenken i e-posten vi har sendt deg. + Fjern %s\? + Telefonnummer + Ingen e-post er lagt til kontoen din + E-post adresser + Autentisering er påkrevd + Du kan ikke gjøre dette fra Element mobile + Bekreft passordet ditt + Vis applikasjonsinformasjonen i systeminnstillingene. + App info + Ingen telefonnummer er lagt til kontoen din + Tredjeparts varsler + Legg til på startskjerm + Forlat samtalen + Avprioritere + Favoritt + Alle meldinger (støyende) + + %1$s rom funnet for %2$s + %1$s rom funnet for %2$s + + Bla gjennom katalogen + Skriv inn et rom-ID eller et romalias + Start chat + LAV PRIORITET + FAVORITTER + DIREKTIV + BLI MED + Søking i krypterte rom støttes ikke ennå. + FOLK + Årsak til å rapportere dette innholdet + Misdannet ID. Bør være en e-postadresse eller en Matrix ID som \'@localpart: domain\' + Godta bare sertifikatet hvis serveradministratoren har publisert et fingeravtrykk som samsvarer med det over. + Sertifikatet er endret fra en tidligere klarert til en som ikke er klarert. Serveren kan ha fornyet sertifikatet. Kontakt serveradministratoren for forventet fingeravtrykk. + Sertifikatet har endret seg fra et som telefonen din klarerte. Dette er veldig uvanlig. Det anbefales at du IKKE godtar dette nye sertifikatet. + Hvis serveradministratoren har sagt at dette forventes, må du forsikre deg om at fingeravtrykket nedenfor samsvarer med fingeravtrykket du har fått. + Dette kan bety at noen ondskapsfullt avlytter trafikken din, eller at telefonen ikke stoler på sertifikatet fra den eksterne serveren. + Kunne ikke bekrefte identiteten til den eksterne serveren. + Fingeravtrykk (%s): + Ikke stol på + Du har ikke tillatelse til å legge ut innlegg i dette rommet + Slett usendte meldinger + Send usendte meldinger på nytt + Send alle på nytt + Meldinger ikke sendt på grunn av ukjente økter. %1$s eller %2$s nå\? + Meldinger ikke sendt. %1$s eller %2$s nå\? + Tilkoblingen til serveren har gått tapt. + Send et svar (ukryptert)… + Send et kryptert svar… + Send en melding (ukryptert)… + Send en kryptert melding… + E-post eller Matrix ID + Vennligst skriv inn en eller flere e-postadresser eller Matrix ID + Inviter bruker etter ID + Kun Matrix brukere + LOKALE KONTAKTER (%d) + Inviter etter ID + Grunn + Å forby bruker vil sparke dem fra dette rommet og forhindre at de blir med igjen. + Grunn til å forby + sparke bruker vil fjerne dem fra dette rommet. +\n +\nFor å forhindre at de blir med igjen, bør du forby dem i stedet. + Grunn til å sparke + Spark bruker + Er du sikker på at du vil avbryte invitasjonen til denne brukeren\? + Avbryt invitasjonen + Oppheving av denne brukeren viser alle meldinger fra dem igjen. + Avignorer bruker + Hvis du ignorerer denne brukeren, fjernes meldingene fra rommene du deler. +\n +\nDu kan når som helst reversere denne handlingen i de generelle innstillingene. + Degradere + Du vil ikke kunne angre denne endringen ettersom du degrerer deg selv. Hvis du er den siste privilegerte brukeren i rommet, vil det være umulig å få tilbake privilegiene. + Degradere deg selv\? + Du vil ikke kunne angre denne endringen ettersom du promoterer brukeren til å ha samme kraftnivå som deg selv. +\nEr du sikker\? + Vis øktliste + Nevne + Bruker-ID, navn eller e-post + Tilbakestill til normal bruker + Avbryt invitasjonen + SESSJONER + RING + ADMIN VERKTØY + Er du sikker på at du vil fjerne %s fra denne chatten\? + Er du sikker på at du vil forlate rommet\? + Legg til medlem + Ny chat + Legg til en identitetsserver i innstillingene dine for å utføre denne handlingen. + Dette er en forhåndsvisning av dette rommet. Rominteraksjoner er deaktivert. + et rom + Du prøver å få tilgang til %s. Vil du være med for å delta i diskusjonen\? + Denne invitasjonen ble sendt til %s, som ikke er tilknyttet denne kontoen. +\nDet kan være lurt å logge på med en annen konto, eller legge til denne e-posten i kontoen din. + Du er invitert til å bli med i dette rommet av %s + Gå til første uleste melding. + Åpne topptekst + Liste medlemmer + Lagre i nedlastinger\? + Tillat tillatelse til å få tilgang til kontaktene dine. + For å skanne en QR-kode, må du gi tilgang til kameraet. + Beklager. Handlingen ble ikke utført på grunn av manglende tillatelser + Element kan sjekke adresseboken din for å finne andre Matrix-brukere basert på e-post og telefonnummer. +\n +\nEr du enig i å dele adresseboken for dette formålet\? + Element kan sjekke adresseboken din for å finne andre Matrix-brukere basert på e-post og telefonnummer. Hvis du godtar å dele adresseboken din for dette formålet, vennligst gi tilgang til neste popup. + Element trenger tillatelse for å få tilgang til kameraet og mikrofonen for å utføre videosamtaler. +\n +\nTillat tilgang til de neste popup-vinduene for å kunne ringe. + " +\n +\nTillat tilgang i neste popup for å kunne ringe." + Element trenger tillatelse for å få tilgang til mikrofonen din for å utføre lydanrop. + " +\n +\nTillat tilgang i neste popup for å kunne ringe." + Element trenger tillatelse for å få tilgang til kameraet ditt for å ta bilder og videosamtaler. + Element trenger tillatelse for å få tilgang til bilde- og videobiblioteket ditt for å sende og lagre vedlegg. +\n +\nTillat tilgang i neste popup for å kunne sende filer fra telefonen din. + Kan ikke ta opp video + Ta et bilde eller en video + samtale besvart andre steder + Kan ikke initialisere kameraet + Medietilkobling mislyktes + Gå tilbake til samtalen + Aktiv samtale (%s) + Innkommende taleanrop + Innkommende videosamtale + Innkommende anrop + Ringer… + Anrop avsluttet + Anrop kobler til… + Samtalen er tilkoblet + Ring + Velg ringetone for samtaler: + Ringetone for innkommende samtaler + Vil bruke %s som assistanse når hjemmeserveren din ikke tilbyr en (IP-adressen din blir delt under en samtale) + Tillat reservehjelpsserver + Bruk standard Element-ringetone for innkommende anrop + Be om bekreftelse før du starter en samtale + Forhindre utilsiktet samtale + Romemne + %d s + + %d medlemskapsendring + %d medlemskapsendringer + + Gruppeliste + Start Element på en annen enhet som kan dekryptere meldingen, slik at den kan sende nøklene til denne økten. + Forespørsel sendt + Nøkkelforespørsel sendt. + SSL-feil: identiteten til jevnaldrende er ikke bekreftet. + Kan ikke nå en hjemmeserver på denne URL-en, sjekk den + Dette er ikke en gyldig Matrix-serveradresse + Denne URL-en er ikke tilgjengelig, sjekk den + Kan ikke registrere: e-post eierskap feil + Fjern publiseringen + Legg til + Begynn å chatte + [%1$s] +\nDenne feilen er utenfor kontroll av Element, og ifølge Google indikerer denne feilen at enheten har for mange apper registrert hos FCM. Feilen oppstår bare i tilfeller der det er ekstremt mange apper, så det bør ikke påvirke gjennomsnittsbrukeren. + Vil du skjule alle meldinger fra denne brukeren\? +\n +\nMerk at denne handlingen starter appen på nytt, og det kan ta litt tid. + Er du sikker på at du vil invitere %s til denne chatten\? \ No newline at end of file diff --git a/vector/src/main/res/values-nn/strings.xml b/vector/src/main/res/values-nn/strings.xml index fcd0ba9e15..2ba928195f 100644 --- a/vector/src/main/res/values-nn/strings.xml +++ b/vector/src/main/res/values-nn/strings.xml @@ -1,17 +1,14 @@ - + nn NO - Lyst tema Mørkt tema Svart tema - Synkroniserar… Lyttar etter hendingar Bråkete varsel Stille varsel - Meldingar Rom Innstillingar @@ -20,11 +17,8 @@ Feilrapport Felleskapsdetaljar Send eit klistremerke - Tredjepartilisensar - Lastar… - Greitt Avbryt Lagra @@ -60,7 +54,6 @@ eller Inviter Fråkopla - Gå ut Handlingar Logg av @@ -74,25 +67,20 @@ Lat att Kopier til utklippstavla Skru av - Stadfesting Åtvaring - Heim Yndlingar Folk Rom Samfund - Filtrer romnamn Filtrer yndlingar Filtrer folk Filtrer romnamn Filtrer felleskap - Invitasjonar Låg prioritering - Samtalar Lokal adressebok Brukarkatalog @@ -100,20 +88,17 @@ Ingen samtalar Du gav ikkje Element tilgang til dei lokale kontaktane dine Ingen treff - Rom Romkatalog Ingen rom Ingen offentelege rom er tilgjengelege - Ein brukar + %d brukar %d brukarar - Inviter Fellesskap Ingen grupper - Send loggar Send krasjrapportar Send skjermbilde @@ -125,14 +110,11 @@ Det verkar som du ristar mobilen i vonbrot. Ønskjer du å opne skjerm for feilrapport \? Programmet krasja sist gong. Ønskjer du å opne skjerm for feilrapport \? Rist i sinne for å rapportera feil - Feilrapporten vart sendt Fekk ikkje til å senda feilrapporten (%s) Framgang (%s%%) - Send inn i Lese - Gå inn i romet Brukarnamn Lag brukar @@ -141,28 +123,21 @@ Heimtenar-URL Identitetstenar-URL Søk - Start ny samtale Start talesamtale Start videosamtale - Send tale - Er du sikker på at du vil starta ein ny samtale med %s\? Er du sikker på at du vil starta ein ny talesamtale\? Er du sikker på at du vil starta ein ny videosamtale\? - Send filer Send klistremerke Ta bilete eller video Ta bilete Ta video - Du har enno ingen klistremerkepakker skrudde på. Legg til nokre no\? - hald fram med… Beklagar, det vart ikkje funne nokon ekstern applikasjon som kan fullføre handlinga. - Logg inn Lag konto Send inn @@ -208,7 +183,6 @@ Ein e-post vart send til %s. Når du har opna linken den inneheld, klikk under. Fekk ikkje til å stadfesta e-postadressa: sjå til at du klikka på lenken i e-posten Passordet ditt vart nullstilt. Du vart logga ut av alle sesjonar og får ikkje push-varsel lenger. For å skru varsel på att, logg inn att på kvar eining. - URL-en må starta på http[s]:// Fekk ikkje til å logga inn: Nettverksfeil Fekk ikkje til å logga inn @@ -216,7 +190,6 @@ Fekk ikkje til å registrere Fekk ikkje til å registrere: feil med e-posteigarskap Skriv inn ein gyldig URL - Brukarnamnet/passordet er ikkje gyldig Den oppgjevne tilgangsnøkkelen vart ikkje kjent att Feilformatert JSON @@ -224,40 +197,29 @@ For mange førespurnader vart sendt Brukarnamnet er allereie i bruk E-postlenken har ikkje blitt opna endå - Etterspør på nytt krypteringsnøkklar frå dei andre einingane dine. - Nøkkelførespurnaden er sendt. - Førespurnaden er send Start Element på ein annan eining som kan dekryptere meldingen, slik at den kan sende nøkklane til denne sesjonen - Les kvitteringsliste - Gruppeliste - - 1 endring i medlemskap + %d endring i medlemskap %d endringar i medlemskap - Send som Original Stor Middels Liten - Avbryt nedlasting\? Avbryt opplasting\? %d s %1$dm %2$ds - I går I dag - Romnamn Romemne - Ring Samtalen er kopla opp Koplar saman samtalar… @@ -267,14 +229,11 @@ Innkommande videosamtale Innkomande talesamtale Samtalen er i gang… - Den andre parten tok ikkje samtalen. Klarar ikkje å skru på kameraet Røyret vart teke ein annan stad - Ta bilete eller video Kan ikkje spela inn video - Info Element treng tilgang til bilete- og videobiblioteket for å senda og lagra vedlegg. \n @@ -295,60 +254,50 @@ Element treng tilgang til kontaktliste for å finna andre Matrix-brukarar basert på e-post og telefonnummer. \n \nSamtykker du til å dele adresseboka for dette føremålet \? - Beklagar. Grunna manglande tilgangar, vart ikkje handlinga utført - Lagra Lagra til nedlastingar\? JA NEI Gå fram - Ta vekk Bli med Førehandsvisning Avvis - Medlemsoversikt Opne overskrift Synkroniserer… Hopp til første uleste melding. - Du vart invitert med i rommet av %s Invitasjonen vart sendt til %s, som ikkje er assosiert med denne kontoen. \nDu kan logge inn med ein annan konto, eller legge til denne e-postadressa i din konto. Du prøver å gå inn i %s. Ønskjer du å bli med for å delta i diskusjonen\? eit rom Dette er ei førehandsvisning av rommet. Interaksjonar med rommet er slått av. - Ny samtale Legg til medlem - 1 aktiv medlem + %d aktiv medlem %d aktive medlem - 1 medlem + %d medlem %d medlem 1 medlem - Forlat rom Er du sikker på at du vil forlata rommet\? Er du sikker på at du vil ta vekk %s frå denne samtalen\? Lag - Tilkopla Fråkopla Fråverande %1$s no %1$s %2$s sidan - ADMINISTRATORVERKTY RØYSTSAMTALA - DIREKTESAMTALE + Folk SESJONAR - Inviter Forlat dette rommet Fjern frå dette romet @@ -364,19 +313,15 @@ Vis sesjonsliste Du vil ikkje kunne angre denne endringa, då du promoterar brukaren til å ha same tilgangsnivå som deg sjølv. \nEr du sikker på dette\? - Er du sikker på at du vil invitera %s inn til samtala\? Er du trygg på at du vil stengja brukaren ute frå samtala\? - Inviter med ID LOKALE KONTAKTAR (%d) BRUKARKATALOG (%s) Berre for Matrix-brukarar - Inviter inn brukarar med ID Ver venleg og skriv ei eller fleire e-postadresser eller Matrix-IDar inn Epost eller Matrix-ID - Søk %s skriv… %1$s og %2$s skriv… @@ -395,10 +340,9 @@ Fila vart ikkje funne Du har ikkje løyve til å senda meldingar i dette rommet - 1 ny melding + %d ny melding %d nye meldingar - Stol på Ikkje stol på Logg ut @@ -410,7 +354,6 @@ Sertifikatet har forandra seg frå det som var stolt på av mobilen din. Dette er SÆRS UVANLEG. Det er tilrådd å IKKJE GODKJENNA dette nye sertifikatet. Sertifikatet har endra seg frå eit som tidlegare var stole på, til eit som ikkje er det. Det kan henda at tenaren har fornya sertifikatet. Snakk med administrator for å få det forventa fingeravtrykket. Godkjenn BERRE sertifikatet viss tenaradministratoren har publisert eit fingeravtrykk som samsvarar med det over. - Romdetaljar Folk Filer @@ -418,15 +361,12 @@ Misforma ID. Det bør vera ei epostadressa eller ein Matrix-ID som t.d. \'@lokaldel:domene\' BODNE INN KOMNE INN - Grunnlag til at du rapporterer innhaldet Vil du gøyma alle meldingar frå denne brukaren\? \n \nMerk at detta vil starta applikasjonen på nytt og kan ta litt tid. Brjot av upplastingi Brjot av nedlastingi - - Søk Filtrer rommedlemmar Ingi treff @@ -434,7 +374,6 @@ MELDINGAR FOLK FILER - VERT MED UTVAL YNDLINGAR @@ -446,10 +385,9 @@ Vert med i romet Vert med i eit rom Skriv inn ein rom-ID eller eit romalias - Bla gjennom katalog - 1 rom + %d rom %d rom @@ -457,7 +395,6 @@ Fann %1$s rom fyr %2$s Søkjer gjennom katalogen… - Alle meldingar (bråkete) Alle meldingar Berre nemningar @@ -467,8 +404,7 @@ Direktesamtale Forlat samtale Gløym - Lag snarveg på heimskjermen - + Legg til på heimskjermen Meldingar Innstillingar Versjon @@ -476,7 +412,6 @@ Informasjon frå tredjepart Opphavsrett Personvern - Profilbilete Visingsnamn Epost @@ -485,7 +420,6 @@ Legg til telefonnummer Vis informasjon om appen i systeminnstillingane Informasjon om applikasjonen - Personvern for varslingar Vanleg Minska personvern @@ -495,12 +429,10 @@ • Meldingsinnhaldet i varselet ertrygt henta beinveges frå Matrix-heimtenaren • Varsel inneheld meta- og meldingsdata • Varsel syner ikkje meldingsinnhald - Varselljod - Skru på varsel fyr denne brukaren + Skru på varslingar for denne kontoen Aktiver varslingar for denne sesjonen Skru skjermen på i 3 sekund - Meldingar som inneheld visingsnamnet mitt Meldingar som inneheld brukarnamnet mitt Meldingar i ein-og-ein-samtalar @@ -508,13 +440,11 @@ Når eg blir invitert til eit rom Invitasjon til samtale Meldingar frå botar - Køyr ved oppstart Bakgrunnsamstilling Skru på bakgrunnsamstilling Samstillingsfyrespurnaden fekk tidsavbrot Forsinkelse mellom kvar synkronisering - Versjon olm versjon Vilkår for bruk @@ -524,7 +454,6 @@ Tøm buffer Tøm mediabuffer Behald mediefiler - Brukarinnstillingar Varsel Ignorerte brukarar @@ -544,23 +473,18 @@ Vis tidspunkt i 12-timarsformat Rist ved nemning Førehandsvis medium før avsending - Deaktiver konto Deaktiver kontoen min - - Varselpersonvern + Personvern ved varslingar Element kan køyra i bakgrunnen for å sikkert og privat halda styr på varsla dine (dette kan påverka batteribruk). Gje tillating vel noko anna - Statistikk Send statistikkdata Element samlar anonym statistikk inn for å forbetra applikasjonen. Ver venleg og skru statistikkinnsamling på for å hjelpa oss med å forbetra Element. Ja, eg vil hjelpa til! - Datasparingsmodus - Informasjon om sesjon ID Offentleg namn @@ -572,22 +496,18 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Stadfesting Passord: Send inn - Logga inn som Heimtenar Identitetstenar - Brukargrensesnitt Språk Vel språk - Ventar på verifikasjon Ver venleg og sjekk eposten din og klikk på lenkja han inneheld. Når det er gjort, klikk gå fram. Fekk ikkje til å stadfesta e-postadressa. Ver venleg og sjekk e-posten din og klikk på lenkja han inneheld. Når det er gjort, klikk gå fram E-postadressa er allereie i bruk Fann ikkje e-postadressa Telefonnummeret er allereie i bruk. - Forandr passordet Gjeldande passord Nytt passord @@ -595,13 +515,9 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Fekk ikkje til å oppdatera passordet Passordet ditt vart oppdatert Vis alle meldingane frå %s\? Merk at denne handlinga gjer at applikasjonen startar på nytt og kan taka litt tid. - Er du sikker på at du vil fjerna varselmålet? - Er du sikker på at du vil fjerna %1$s %2$s? - Vel eit land - Land Ver venleg og vel eit land Telefonnummer @@ -611,26 +527,20 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Skriv ein stadfestingskode inn Noko gjekk galt under stadfestinga av telefonummeret ditt Kode - - Etikett Du er førebels ikkje med i nokre fellesskap. - 3 dagar 1 veke 1 månad For alltid - Rombilete Romnamn Emne Rommerke Merka som: - Gjer til yndling Lågrett Ingen - Tilgang og synlegheit Vis dette rommet i romkatalogen Varsel @@ -638,19 +548,15 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Romhistoria si lesbarheit Kven kan lesa historia? Kven kan koma inn i rommet? - Kven som helst Berre medlemmar (frå då innstillinga er vald) Berre medlemmar (frå då dei vart bodne inn) Berre medlemmar (frå då dei kom inn) - For å lenkja eit rom må det ha ei adresse. Berre folk som har vorte bodne inn Kven som helst som veit romlenkja, sett vekk frå gjester Kven som helst som veit romlenkja, inkluderande gjester - Utestengde brukarar - Avansert Rommet sin interne ID Adresser @@ -661,38 +567,28 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Du må vera logga ut for å kunna skru krypteringa på. Krypter berre til godkjende sesjonar Aldri send krypterte meldingar til ikkje-godkjende sesjonar i dette rommet frå denne sesjonen. - Dette rommet har ingen lokale adresser Ny adresse (t.d. #foo:matrix.org) - Dette rommet viser ikkje etikettar for nokre fellesskap Ny fellesskaps-ID (t.d. +foo:matrix.org) Ugyldig fellesskaps-ID \'%s\' er ikkje ein gyldig fellesskaps-ID - - Ugangbar aliasform \'%s\' er ikkje ei gangbar form for eit alias Du vil ikkje ha spesifisert ei hovudadresse for dette rommet. Hovudadresse-åtvaringar - - Set som Hovudadresse - Fjern som Hovudadresse + Set som hovudadresse + Fjern som hovudadresse Kopier Rom-IDen Kopier Romadressa - Kryptering er skrudd på i dette rommet. Kryptering er skrudd av i dette rommet. Skru kryptering på -(åtvaring: kan ikkje skruast av att!) - +\n(åtvaring: kan ikkje skruast av att!) Utval Preg - %s prøvde å lasta eit spesifikt punkt i rommet sin historikk men klarte ikkje å finna det. - Ende-til-ende-krypteringsinfo - Hendingsinfo Brukar-ID Curve25519-identitetsnykel @@ -700,15 +596,13 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Algoritme Økt-ID Noko gjekk gale med dekrypteringa - Avsendar-sesjonsinformasjon Offentleg namn Offentleg namn - ID + Økt-ID Sesjonsnøkkel Verifikasjon Ed25519-fingeravtrykk - Eksporter E2E-romnøkklar Eksporter romnøkklar Hent nøkklane ut til ei lokal fil @@ -716,59 +610,49 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Skriv passetning inn Stadfest passetninga E2E-romnøkklane vart lagra til \'%s\' Åtvaring: fila kan verta sletta viss app\'en avinstallerast. - Importer E2E-romnøkklar Importer romnøkklar Hent nøkklane inn frå ei lokal fil Hent inn Krypter berre til godkjende sesjonar Aldri send krypterte meldingar til ikkje-godkjende sesjonar frå denne sesjonen - IKKJE Godkjend Godkjend Svartelista - ukjend sesjon ingen - Godkjenn Fjern verifikasjon Set på svartelista Fjern frå svartelista - Verifiser sesjonen For å godkjenna at denne sesjonen er til å stola på, ver venleg og snakk med eigaren på ein anna måte (t.d. ansikt til ansikt eller på telefon) og spør han om nøkkelen han ser i Brukarinnstillingane for denne sesjonen samsvarar med nøkkelen under: Viss det samsvarer, klikk Verifiser-knappen under. Viss det ikkje gjer det, avlyttar nokon andre denne sesjonen og du bør sannsynlegvis svarteliste den. I framtida vil denne verifikasjonsprosessen bli meir forbetra. Eg stadfestar at nøkklane er like - Rommet inneheld ukjende sesjonar Rommet inneheld ukjende sesjonar som ikkje har blitt verifiserte. Det er med andre ord ingen garanti for at sesjonane høyrer til brukarane dei hevdar. Vi tilråder deg å gå gjennom verifikasjonsprosessen for kvar eining før du går vidare, men du kan sende meldingen på nytt utan å godkjenne viss du vil. \n \nUkjende sesjonar: - Vel ein romkatalog Tenaren er kanskje utilgjengeleg eller overlasta Skriv ein heimtenar inn for å få henta opp offentlege rom frå Heimtenar-URL Alle rom på %s-tenaren Skriv her… - - 1 ulest varsla melding + %d ulest varsla melding %d uleste varsla meldingar - 1 ulest varsla melding + %d ulest varsla melding %d uleste varsla meldingar - 1 rom + %d rom %d rom %1$s i %2$s - Søk etter historiske - Skriftstorleik Bitteliten Liten @@ -777,16 +661,14 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Større Størst Enorm - Du trenger tillating til å handsama widgetar i dette rommet Widget-laging mislukkast Lag konferansesamtalar med Jitsi Er du sikker på at du vil slette widgeten frå dette rommet\? - 1 verkande widget - %d verkande widgetar + %d widget på + %d widgetar på - Klarte ikkje å laga widget. Fekk ikkje til å senda førespurnad. Tilgangsnivået må vere eit positivt heiltal. @@ -800,16 +682,13 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Legg til Matrix-applikasjonar Bruk entertasten på tastaturet for å senda meldingar Send talemelding - Du la til den nye sesjonen \'%s\', som etterspør krypteringsnøkklar. Den ikkje-verifiserte sesjonen din \'%s\' etterspør krypteringsnøkklar. Start verifikasjon Del utan verifikasjon Oversjå førespurnaden - Åtvaring! Gruppesamtaling er under utvikling og er kanskje ikkje påliteleg. - Noko gjekk gale med påbodet Påbodet er uattkjend: %s Viser handling @@ -825,48 +704,37 @@ For å gå fram, ver venleg og skriv passordet ditt inn. Forandrar visingsnamnet ditt På/Av markdown For å ordne opp i Matrix-App-administrasjon - Av Bråket - Kryptert melding - Laga Lag fellesskap Fellesskapsnamn Døme Fellesskaps-ID døme - Heim Folk Rom Ingen brukarar - Rom Komne inn Bodne inn Filtrer gruppemedlemmar Filtrer grupperom - Fellesskapssadministratoren har ikkje satt ei lang skildring for dette fellesskapet. - Du vart sparka frå %1$s av %2$s Du var stengd ute frå %1$s av %2$s Grunnlag: %1$s Vert med att Gløym rommet - Alle %s-rom på Matrix - Bruk det innebygde kameraet Lapp-avatar Varselavatar Avatar - For å halda fram med å bruka %1$s-heimtenaren må du sjå over og seia deg einig i vilkåret og føresetnader. Sjå over no - Deaktiver konto Dette gjer at brukaren din vert ubrukeleg til evig tid. Du kjem ikkje til å kunna logga inn, og ingen andre kjem til å kunna melde seg inn med den gamle brukar-IDen din. Brukaren din forlét òg alle rom han er i, og brukardetaljane dine vil verta fjerna frå identitetstenaren. Denne handlinga kan ikkje gjerast om. @@ -876,94 +744,74 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Ver venleg og gløym alle meldingane eg har send når brukarkontoen min vert deaktivert (Åtvaring: dette gjer at framtidige brukarar ikkje får eit fullstendig oversyn av samtalene) For å gå fram, ver venleg og skriv passordet ditt inn: Deaktiver konto - Ver venleg og skriv passordet ditt inn. Rommet har verta erstatta og er ikkje aktivt lenger Samtala går vidare her Rommet er ein vidareføring av ei anna samtale Klikk her for å sjå gamle meldingar - Systemvarsel - - 1s + %ds %ds - 1m + %dm %dm - 1t + %dt %dt - 1d + %dd %dd - "%1$s, " %1$s, og %2$s %1$s %2$s - - 1 valt + %d valt %d valde - 1 medlem - %d medlemer + %d medlem + %d medlem - - 1 rom + %d rom %d rom Kontakt Administratoren - kontakt tenesteadministratoren din - Grunna manglande rettigheiter, er ikkje denne handlinga muleg. Ressursgrensa er Forbigått Heimtenaren har truffe ei av ressursgrensene sine so nokre brukarar vil ikkje kunna logga inn. Heimtenaren har forbigått ei av ressursgrensene sine. - Heimtenaren har truffe den Månadlege Grensa si for Aktive Brukarar, so nokre brukarar vil ikkje kunna logga inn. Heimtenaren har truffe den Månadlege Grensa si for Aktive Brukarar. - Ver venleg og %s for å heva grensa. Ver venleg og %s for å halda fram med å bruka tenesten. - Status.im-tema - Ring likevel Aksepter - Feil - Hopp over Ferdig Avbryt Ignorer - Sikker på at du vil logga ut\? Merk som lest Venligast sjå over og godta retningslinjene til heimtenaren: - Det gjeng ikkje å nå URL-en, gjer vel og sjå til honom Oppringingar Bruk standard Element-ringetone for innkommande samtalar Ringetone for innkommande samtalar Vel ringetone for samtalar: - Ein videosamtale pågår… - Spark Grunn - Avanserte varslingsinnstillingar Prioritet på varsel ut ifrå hendingar - Løys problem med varslingar Diagnostikk for feilsøking Køyr testar @@ -971,30 +819,25 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Det grunnleggjande er i orden. Om du framleis ikkje får varsel, send inn ei feilmelding så vi kan undersøke dette. Ein eller fleire testar har feila. Prøv føreslegne løysing(ar). Éin eller fleire prøvar gjekk galne. Gjer vel og send inn ei feilmelding so me kann sjå nærare på det. - Systeminnstillingar. Varsel er skrudde på i systeminnstillingane. Varsel er skrudde av i systeminnstillingane. \nGjer vel og sjå på systeminnstillingane. Opna innstillingane - Brukarinnstillingar. Varsel er skrudde på fyr brukaren din. Varsel er skrudde av fyr brukaren din. \nGjer vel og sjå på brukarinnstillingane. Skru på - Sesjonsinnstillingar. Varslingar er aktivert for denne sesjonen. Varslingar er deaktivert for denne sesjonen. \nSjekk Element-innstillingane. Skru på - setter opp tenesta Sikkerheitskopi av nøkkel Bruk sikkerheitskopiering av nøkkel Stadfest sesjon - Sikkerheitskopi av nøklar er ikkje ferdig, vent litt… Om du loggar ut no, vil dine krypterte meldingar gå tapt Sikkerheitskopi av nøklar pågår, viss du loggar ut no vil du miste tilgang til krypterte meldingar. @@ -1005,23 +848,19 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Er du sikker \? Sikkerheitskopier Du vil miste tilgang til dine krypterte meldingar, med mindre nøklane dine er sikkerheitskopierte før utlogging. - Bli Ingen Trekk tilbake Koble frå Sjå gjennom Avvis - Ingen identitetstenar er satt opp. - Samtale feila fordi tenaren er satt opp feil Be administratoren for din heimetenar (%1$s) om, å setta opp ein \"TURN-server\" for å handtera samtalar på rett måte. \n \nEventuelt, kan du prøve å nytta den offentlege tenaren på %2$s, men dette vil kanskje ikkje vere like stabilt og IP-adressa di vil bli delt mot den tenaren. Du kan også styre dette under Innstillingar. Prøv med %s Spør meg ikkje om att - Logg inn med SSO (single sign-on) Sett e-postadresse for gjenoppretting av konto, så kan du og seinare bli synleg for folk som kjenner deg. Sett telefonnummer, så kan du og seinare bli synleg for folk som kjenner deg. @@ -1037,8 +876,6 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Stadfest ditt passord Denne handlinga kan ikkje utførast frå Element på mobil Authentisering er påkrevd - - Integrasjonar Bruk ein integrasjonshandterar (Integration Manager) for å handtere botar, bruer, tillegg og klistermerkepakker. \nIntegrasjonshandterarar hentar konfigurasjonsdata, og kan endra tillegg, senda rominvitasjonar og sette tilgangsnivå på vegne av deg. @@ -1046,7 +883,6 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Dette valet krev eit tredjepartsprogram for å registrere meldingane. Last rom-medlemmar etter behov (lazy-load) Heimetenaren din støttar ikkje såklalla lazy-loading av rommelemar endå. Prøv igjen seinare. - Sikre meldingar med denne brukaren er ende-til-ende kryptert, dei kan ikkje bli lesne av tredje partar. Anna informasjon frå tredjepart Meldingar med denne brukaren er ende-til-ende kryptert, dei kan ikkje bli lesne av tredje part. @@ -1054,32 +890,22 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Still inn samtale-varsel Set opp stille-varsel Set opp LED-farge, vibrasjon eller lyd… - - Vis bli-med/forlat hendelsar Invitasjonar, utkastingar og utestengingar gjeld ikkje dette. Opna i nettlesar - Hentar sikkerheitskopiversjon… Versjon Matrix SDK versjon Innstillingar Sikkerheit og personvern - Tale & Video - Hjelp & Om - - + Tale og video + Hjelp og om Vis skjulte hendelsar i historikken - Aktiver swipe-for-å-svare i historikken - Forlat rommet Uleste meldingar - Denne heime-tenaren køyrer ein gammal versjon, du kan derfor ikkje kopla til. Be administrator om å oppgradere. - Etter aktivering, så kan ikkje kryptering bli deaktivert. - Sikkerheit Få meir info Rominnstillingar @@ -1089,18 +915,49 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Tilpassa Invitasjonar Brukarar - Administrator i %1$s Moderator i %1$s Tilpassa (%1$d) i %2$s - Denne økta klarde ikkje å dele denne verifikasjonen med dine andre økter. \nVerifikasjonsdata er lagra lokalt, og vil bli delt i ein framtidig versjon av programmet. - Historikk - Etter aktivering, så kan ikkje kryptering bli deaktivert. - Fullstendig sikkerheit - - + Formater meldingar skrivne med Markdown-syntaksen før dei blir sendt. Dette gjer at ein kan t.d. bruke stjerne(*) for å vise tekst i kursiv. + Bruk Markdown-formatering + Still inn korleis e-postadresser og telefonnummer er knytta til Matrix-kontoen din + Still inn korleis kontoen din kan bli oppdaga. + E-postadresser og telefonnummer + Synlegheit + Avanserte innstillingar + Avanserte og tilpassa innstillingar + Generelt + Spel av + Dette telefonnummeret er allereie definert. + Skru HD av + Front + Trådlaus hovudtelefon + Høgtalar + Vel eining for lyd + Element-samtalen feila + Ingen fleire resultat + Suksess + Legg til + Legg på + Aksepter + Du kan ikkje starta ein talesamtale med deg sjølv, vent til at andre deltakarar aksepterer invitasjonen + Du kan ikkje starta ein talesamtale med deg sjølv + Møter nyttar Jitsi sine sikkerheit- og tilgangsreglar. Alle medlemmar av rommet vil sjå ei invitasjonslenkje så lenge møtet pågår. + Start møte med lyd + Start møte med video + Ein konferansesamtale er i gong allereie! + Du har ikkje lov til å starta ein samtale + Du har ikkje lov til å starta ein samtale i dette rommet + Du har ikkje lov til å starta ein konferansesamtale + Du har ikkje lov til å starta ein konferansesamtale i dette rommet + Start samtale + Nullstill + Pause + Folk + Folk + \ No newline at end of file diff --git a/vector/src/main/res/values-pl/strings.xml b/vector/src/main/res/values-pl/strings.xml index a7d29516b2..b3008305f3 100644 --- a/vector/src/main/res/values-pl/strings.xml +++ b/vector/src/main/res/values-pl/strings.xml @@ -72,9 +72,10 @@ Brak pokojów Nie są dostępne publiczne pokoje - 1 użytkownik + %d użytkownik %d użytkowników %d użytkowników + %d użytkowników Wyślij dzienniki Wyślij dzienniki awarii @@ -156,7 +157,7 @@ Ta nazwa użytkownika jest już używana Nie kliknięto odnośnika z wiadomości e-mail Przeczytaj listę odbiorców - "Wyślij jako " + Wyślij jako Oryginalny Duży Średni @@ -413,7 +414,7 @@ Zauważ, że ta czynność spowoduje ponowne uruchomienie aplikacji i może to t ID sesji Nazwa publiczna Nazwa publiczna - ID + ID sesji Weryfikacja Odcisk palca Ed25519 Eksportuj @@ -498,12 +499,12 @@ Możesz dodać adres e-mail do swojego profilu w ustawieniach. Rozmówca nie połączył się. - - -Zezwól na dostęp w następnym oknie aby móc wykonać połączenie. - - -Zezwól na dostęp w następnym oknie aby móc wykonać połączenie. + " +\n +\nZezwól na dostęp w następnym oknie aby móc wykonać połączenie." + " +\n +\nZezwól na dostęp w następnym oknie aby móc wykonać połączenie." Element wymaga dostępu do kamery i mikrofonu, aby przeprowadzać rozmowy wideo. Przyznaj dostęp w następnym oknie. @@ -563,7 +564,7 @@ Jesteś pewien? Wszystkie wiadomości Tylko wspomnienia Wycisz - Dodaj skrót do ekranu domowego + Dodaj do ekranu domowego Informacje o trzecich stronach Pokaż informacje o aplikacji w ustawieniach systemu. Dźwięk powiadomień @@ -762,9 +763,10 @@ Widoczność wiadomości w Matrix jest podobna do wiadomości e-mail. Nasze zapo Opuszcza pokój Włącza/Wyłącza markdown - 1 członek + %d członek %d członków + 1 pokój @@ -779,24 +781,28 @@ Widoczność wiadomości w Matrix jest podobna do wiadomości e-mail. Nasze zapo Alerty systemowe Jeżeli to możliwe, proszę napisz opis w języku angielskim. - 1 sekunda + %d sekunda %d sek. + - 1 minuta + %d minuta %d min. + - 1 godzina + % godzina %s godz. + - 1 dzień + %d dzień %d dni + 1 zaznaczone @@ -971,7 +977,7 @@ Spróbuj uruchomić ponownie aplikację. Wiadomości Bezpośrednie Nowy pokój STWÓRZ - Nazwa pokoju + Nazwa Publiczny Każdy będzie mógł dołączyć do tego pokoju Ponów @@ -1090,7 +1096,7 @@ Spróbuj uruchomić ponownie aplikację. Zgłoś tę treść Powód zgłoszenia treści ZGŁOŚ - ZABLOKUJ UŻYTKOWNIKA + IGNORUJ UŻYTKOWNIKA Treść zgłoszona Zgłoszone jako spam Weyfikacja zostaje anulowana. @@ -1124,7 +1130,7 @@ Spróbuj uruchomić ponownie aplikację. Ustawienia pokoju Powiadomienia Opuść pokój - Włącz szyfrowanie end-to-end + Włącz szyfrowanie end-to-end… Brak Brak skonfigurowanego serwera tożsamości. Poproś administratora serwera (%1$s) o skonfigurowanie usługi TURN, aby połączenia mogły działać prawidłowo. @@ -1157,10 +1163,10 @@ Spróbuj uruchomić ponownie aplikację. Dla zwiększenia bezpieczeństwa, zalecamy aby wykonać ten krok osobiście lub przez inne zaufane środki komunikacji. Treść została zgłoszona. \n -\nJeśli nie chcesz więcej otrzymywać wiadomości od tego użytkownika, możesz go zablokować by ukryć jego wiadomości +\nJeśli nie chcesz więcej otrzymywać wiadomości od tego użytkownika, możesz go ignorować by ukryć jego wiadomości. Treść została zgłoszona jako spam. \n -\nJeśli nie chcesz więcej widzieć treści tego użytkownika,możesz go zablokować by ukryć jego wiadomości +\nJeśli nie chcesz więcej widzieć treści tego użytkownika,możesz go ignorować by ukryć jego wiadomości. Sprawdź ograniczenia pracy w tle Wyłącz ograniczenia Konfiguruj powiadomienia połączeń @@ -1178,12 +1184,12 @@ Spróbuj uruchomić ponownie aplikację. Aktywuj uruchamianie przy starcie systemu Restrykcje dotyczące działania aplikacji w tle są wyłączone dla Element. Test powinen zostać uruchomiony używając danych komórkowych (bez WIFI). \n%1$s - "Restrykcje dotyczące działania aplikacji w tle są włączone dla Element. -\nPraca którą aplikacja próbuje wykonać będzie agresywnie ograniczona podczas działania w tle i może wpłynąć na wyświetlanie powiadomień. -\n%1$s" + Restrykcje dotyczące działania aplikacji w tle są włączone dla Element. +\nPraca którą aplikacja próbuje wykonać będzie agresywnie ograniczona podczas działania w tle i może wpłynąć na wyświetlanie powiadomień. +\n%1$s Na Element nie ma wpływu Optymalizacja Baterii. Jeżeli użytkownik pozostawi urządzenie odłączone od zasilania oraz nieużywane przez określony okres, z wyłączonym ekranem, urządzenie przejdzie w tryb Doze. Uniemożliwia to aplikacjom dostęp do sieci i opóźnia ich zadania, synchonizację oraz standardowe alarmy. - Tryb synchronizacji w tle (eksperymentalny) + Tryb synchronizacji w tle Zoptymalizowano dla baterii Element będzie synchronizował się w tle w sposób który oszczędza limitowane zasoby urządzenia (baterię). \nW zależności od stanu zasobów urządzenia, synchronizacja może być opóźniania przez system operacyjny. @@ -1212,9 +1218,10 @@ Spróbuj uruchomić ponownie aplikację. Domyślne źródło mediów Odzyskiwanie zaszyforwanych wiadomości - %1$s: 1 wiadomość + %1$s: %2$d wiadomość %1$s: %2$d wiadomości + %d powiadomienie @@ -1269,9 +1276,9 @@ Spróbuj uruchomić ponownie aplikację. Zrobiłem kopię Zapisz Klucz Odzyskiwania Zapisz jako plik - "Klucz odzyskiwania został zapisany do \'%s\'. + Klucz odzyskiwania został zapisany do \'%s\'. \n -\nUwaga: plik może zostać usunięty, jeżeli aplikacja jest odinstalowana." +\nUwaga: plik może zostać usunięty, jeżeli aplikacja jest odinstalowana. Kopia zapasowa już istnieje na Twoim serwerze domowym Wygląda na to, iż kopia zapasowa kluczy została skonfigurowana za pomocą innej sesji. Czy chcesz zastąpić ją tą, którą tworzysz\? Generowanie Klucza Odzyskiwania używając hasła, proces może zająć kilka sekund. @@ -1345,8 +1352,8 @@ Spróbuj uruchomić ponownie aplikację. Otrzymano nieprawidłową wiadomość Dołącz do pokoju, aby rozpocząć korzystanie z aplikacji. Zapoznaj się z nieprzeczytanymi wiadomościami tutaj - Twoje rozmowy bezpośrednie będą wyświetlane tutaj - Twoje pokoje będą wyświetlane tutaj + Twoje rozmowy bezpośrednie będą wyświetlane tutaj. Naciśnij przycisk + żeby rozpocząć nową. + Twoje pokoje będą wyświetlane tutaj. Naciśnij przycisk +żeby znaleźć istniejące bądź utworzyć nowy. Nieprawidłowe zdarzenie, nie można wyświetlić Podgląd globalnego, publicznego pokoju nie jest wciąż wspierany w Element Wystąpił błąd podczas otrzymywania zaufanych informacji @@ -1406,17 +1413,18 @@ Spróbuj uruchomić ponownie aplikację. odczytano przez %1$s oraz %2$s %s odczytał - 1 użytkownik odczytał + %d użytkownik odczytał %d użytkowników odczytało + Wystąpił błąd poczas otrzymywania załącznika. Audio Nie można obsłużyć otrzymanych danych Zgłoszono jako nieodpowiedni - Zawartość została zgłoszona jako niewłaścwa. + Zawartość została zgłoszona jako niewłaściwa. \n -\nJeżeli nie chcesz widzieć treści od tego użytkownika, możesz go zablokować aby ukryć jego wiadomości +\nJeżeli nie chcesz widzieć treści od tego użytkownika, możesz go zablokować aby ukryć jego wiadomości. Element potrzebuje uprawnień aby zapisywać klucze E2E na dysku. \n \nPozwól na dostęp w następnym oknie aby móc eksportować klucze ręcznie. @@ -1429,7 +1437,7 @@ Spróbuj uruchomić ponownie aplikację. %1$s ustawił(-a) pokój dostępnym publicznie dla każdego, kto zna link. %1$s ustawił(-a) pokój tylko dla zaproszonych. Nieprzeczytane wiadomości - Wyzwól swoją komunikację + Wyzwól swoją komunikację. Czatuj z osobami bezpośrednio lub w grupach Pozostaw konwersacje prywatnymi za pomocą szyfrowania Rozszerz i dopasuj swoje doświadczenie @@ -1763,7 +1771,7 @@ Spróbuj uruchomić ponownie aplikację. Zmień serwer tożsamości Aparat Obecnie nie ma połączenia z siecią - Zablokuj użytkownika + Ignoruj użytkownika Złóż sugestię Tryb programisty aktywuje ukryte funkcje i może również spowodować, że aplikacja będzie mniej stabilna. Tylko dla programistów! Wiadomości w tym pokoju nie są szyfrowane end-to-end. @@ -1789,4 +1797,519 @@ Spróbuj uruchomić ponownie aplikację. Nie posiadasz wymaganych uprawnień aby rozpocząć połączenie grupowe w tym pokoju Nie posiadasz wymaganych uprawnień do rozpoczęcia połączenia Nie posiadasz wymaganych uprawnień aby rozpocząć połączenie grupowe + Przejrzyj swoje ustawienia aby włączyć powiadomienia PUSH + Powiadomienia PUSH są wyłączone + Nie udało się odblokować użytkownika + Zablokowany przez %1$s + Wycofać zaproszenie dla %1$s\? + Wycofaj zaproszenie + Szukaj kontaktów w Matrix + Lista kontaktów + Twoja lista kontaktów jest pusta + Pozyskiwanie Twoich kontaktów… + Wyszukaj w moich kontaktach + Książka telefoniczna + Twoja książka telefoniczna jest pusta + Dodaj z mojej książki telefonicznej + Zapisz klucz odzyskiwania w + element + DOWIEDZ SIĘ WIĘCEJ + Jesteśmy podekscytowani mogąc oznajmić, że zmieniliśmy nazwę! Twoja aplikacja jest aktualna i jesteś zalogowany(-a) do swojego konta. + Riot nazywa się teraz Element! + Nie masz dostępu do tej wiadomości ponieważ nadawca celowo nie wysłał jej kluczy + Nie masz dostępu do tej wiadomości ponieważ nadawca nie ufa Twojej sesji + Nie masz dostępu do tej wiadomości ponieważ zostałeś zablokowany przez jej nadawcę + Z powodu szyfrowania punkt-punkt, musisz zaczekać na dostarczenie cudzej wiadomości ponieważ związane z nią klucze deszyfrujące nie zostały poprawnie wysłane do Ciebie. + Nie można odszyfrować + Oczekiwanie na tę wiadomość, to może chwilę potrwać + Nie masz dostępu do tej wiadomości + Ustaw awatar + Pomyślnie zmieniono ustawienia pokoju + Temat + Nazwa pokoju + Przechowuj swój Klucz Bezpieczeństwa w chronionym miejscu takim jak menadżer haseł lub sejf. + Wprowadź swoją Frazę Bezpieczeństwa ponownie żeby ją potwierdzić. + Wpisz frazę bezpieczeństwa którą znasz tylko ty, będzie wykorzystywana do zabezpieczania sekretów na twoim serwerze. + Przechowuj swój Klucz Bezpieczeństwa w chronionym miejscu takim jak menadżer haseł lub sejf. + Zapisz Klucz Bezpieczeństwa + Użyj Frazy Bezpieczeństwa + Użyj klucza bezpieczeństwa + Zabezpiecza przeciwko utracie dostępu do zaszyfrowanych wiadomości oraz danych poprzez zapisanie zaszyfrowanych kluczy na Twoim serwerze. + Włącz aparat + Wyłącz aparat + Wyłącz wyciszenie mikrofonu + Wycisz mikrofon + Otwórz konwersację + Rola + Przypisz rolę + Wyślij + Wprowadź adres URL serwera tożsamości + Alternatywnie, możesz wprowadzić adres URL dowolnego serwera tożsamości + Użyj %1$s + Użyj %1$s albo %2$s aby kontynuować. + Dostępne tylko w pokojach szyfrowanych + Skorzystaj z najnowszych aplikacji Element na innych urządzeniach: + Element iOS +\nElement Android + Element Web +\nElement Desktop + Ustaw nowe hasło do konta… + Nie można zapisać pliku multimediów + Nie można dodać pliku multimediów do galerii + Pliki multimedialne dodane do galerii + Włączenie tej opcji spowoduje dodanie flagi FLAG_SECURE do wszystkich Aktywności. Zrestartuj aplikację żeby zastosować zmiany. + Zapobiegaj wykonywaniu zrzutów ekranu z aplikacji + Klucz odzyskiwania do kopii zapasowej kluczy + Podaj hasło do klucza kopii zapasowej aby kontynuować. + %1$s (%2$s) + Generowanie klucza SSSS z klucza odzyskiwania + Generowanie klucza SSSS z hasła (%s) + Podaj klucz odzyskiwania + To nie jest prawidłowy klucz odzyskiwania + Hasło odzyskiwania + Wprowadź %s + Użyj pliku + Wpisz swój %s aby kontynuować + Zweryfikuj siebie i innych aby zapewnić bezpieczeństwo swoich konwersacji + Wiadomość… + To konto zostało zdezaktywowane. + Nieprawidłowa nazwa użytkownika i/lub hasło. Wprowadzone hasło zaczyna się lub kończy od spacji, proszę to sprawdzić. + Wyślij wiadomość jako czysty tekst, bez interpretowania jej jako zapisu w języku znaczników + Ustaw ważność powiadomień w zależności od wydarzenia + Zaszyfrowane wiadomości w konwersacjach grupowych + Zaszyfrowane wiadomości w konwersacjach bezpośrednich + Wiadomości zawierające @room + Konfiguracja powiadomień + Nie udało się zaimportować kluczy + Oczekiwanie na %s… + Prawie gotowe! Oczekiwanie na potwierdzenie… + Prawie gotowe! Czy drugie urządzenie pokazuje taką samą tarczę\? + "Temat: " + Dodaj temat + %s aby poinformować innych czego dotyczy konwersacja w tym pokoju. + To jest początek Twojej rozmowy bezpośredniej z %s. + To jest początek tej konwersacji. + To jest początek %s. + Ty dołączyłeś(-łaś). + %s dołączył(a). + Stworzyłeś(-łaś) i skonfigurowałeś(-łaś) ten pokój. + %s stworzył(a) i skonfigurował(a) ten pokój. + Szyfrowanie wykorzystywane przez ten pokój nie jest obsługiwane + Szyfrowanie wyłączone + Wiadomości w tym pokoju są szyfrowane w trybie punkt-punkt (e2e). + Wiadomości w tym pokoju są szyfrowane punkt-punkt (e2e). Możesz dowiedzieć się więcej i zweryfikować użytkowników w ich profilach. + Szyfrowanie włączone + Jeżeli teraz przerwiesz, możesz utracić zaszyfrowane wiadomości oraz dane jeżeli utracisz dostęp do zalogowanych sesji. +\n +\nMożesz także ustawić Secure Backup i zarządzać swoimi kluczami w Ustawieniach. + Skonfigurowanie Frazy Odzyskiwania pozwala na zabezpieczenie i odblokowanie zaszyfrowanych wiadomości i zaufanych. + Skonfigurowanie Frazy Odzyskiwania pozwala na zabezpieczenie i odblokowanie zaszyfrowanych wiadomości i zaufanych. +\n +\nJeżeli nie chcesz ustawiać Hasła Wiadomości, możesz zamiast tego wygenerować do niej Klucz. + Nie możesz tego zrobić z urządzenia mobilnego + Wydrukuj go i schowaj w bezpiecznym miejscu + Twój %2$s i %1$s są teraz ustawione. +\n +\nPrzechowuj je w bezpiecznym miejscu! Potrzebujesz ich do odblokowania zaszyfrowanych wiadomości i chronionych danych w razie utraty dostępu do wszystkich aktywnych sesji. + Usunąć dane konta typu %1$s\? +\n +\nUwaga, to może prowadzić do nieprzewidywanego zachowania. + Aktywne widżety + %1$s: %2$s %3$s + %1$s: %2$s + Przełącz aparat + Synchronizacja Klucza Użytkownika (User Key) + Synchronizacja Głównego Klucza (Master Key) + Generowanie kluczy bezpieczeństwa z hasła + Publikowanie utworzonych kluczy identyfikacyjnych + Koniec + Chroń go + Gotowe! + Twój klucz odzyskiwania + To może potrwać kilka sekund, proszę o cierpliwość. + Wpisz frazę bezpieczeństwa którą znasz tylko ty, będzie wykorzystywana do zabezpieczania sekretów na twoim serwerze. + Nie używaj Twojego hasła do konta. + Wpisz ponownie Twoje %s żeby je potwierdzić. + Wpisz Twoje %s żeby kontynuować. + Potwierdź %s + Generuj klucz wiadomości + Ustaw %s + Hasło do konta + Klucz wiadomości + Hasło odzyskiwania + Weryfikacja anulowana + Zweryfikuj Twoje urządzenia w Ustawieniach. + Jedno z poniższych mogło zostać skompromitowane: +\n +\n-Twoje hasło +\n-Twój serwer domowy +\n-To urządzenie albo inne urządzenie +\n-Połączenie internetowe używane przez urządzenie +\n +\nZalecamy natychmiastową zmianę Twojego hasła oraz klucza odzyskiwania w Ustawieniach. + Jeżeli anulujesz, nie będziesz w stanie czytać zaszyfrowanych wiadomości na nowym urządzeniu, a inni użytkownicy nie będą mu ufali + Jeżeli anulujesz, nie będziesz w stanie czytać zaszyfrowanych wiadomości na tym urządzeniu, a inni użytkownicy nie będą mu ufali + Twoje konto może być skompromitowane + Naciśnij żeby przejrzeć i zweryfikować + Nowe logowanie. Czy to Ty\? + Eksportuj audyt + Sondaż + MULTIMEDIA + WIDOK + Pokazuj wydarzenia związane ze stanem uczestników w pokoju + + %d sekunda + %d sek. + %d sek. + %d sek. + + Aplikacja odebrała PUSH + Przetestuj wiadomość Push + Odbanuj użytkownika + Powód zbanowania + Wykopanie użytkownika spowoduje usunięcie go z tego pokoju. +\n +\nŻeby zapobiec jego ponownemu dołączeniu należy go zamiast tego zablokować. + Aktywne połączenie (%s) + Zapobiegaj przypadkowym połączeniom + Wycofaj publikację + Dodaj + Skopiuj + Zakończ rozmowę + Zresetuj + Tryb samolotowy jest włączony + Prawie gotowe! Czy %s pokazuje taką samą tarczę\? + Twój administrator serwera zablokował domyślne szyfrowanie punkt-punkt (e2e) w pokojach prywatnych w Wiadomościach Bezpośrednich. + Nie masz uprawnień żeby uaktywnić szyfrowanie w tym pokoju. + Wiadomość bezpośrednia + Domyślnie w %1$s + Opuść + Ustawienia + Operacje administratora + Wiadomości tutaj są zaszyfrowane w trybie punkt-punkt (e2e). +\n +\nTwoje wiadomości są zabezpieczone kłódkami, do których jedynie Ty i Twoi rozmówcy mają unikalne klucze umożliwiające ich otwarcie. + Wiadomości tutaj nie są zaszyfrowane w trybie punkt-punkt (e2e). + Weryfikacja wniosków + Zareagowano: %s + Przyciski botów + Tworzenie pokoju… + Niektóre znaki nie są dozwolone + Podaj adres pokoju + Ten adres jest już w użyciu + Adres pokoju + Możesz aktywować tę opcję jeżeli pokój będzie wykorzystywany jedynie do współpracy z wewnętrznymi zespołami na Twoim serwerze domowym. Ta opcja nie może być zmieniona później. + Zablokuj wszystkich nie będących członkami %s przed dołączeniem do tego pokoju + Ukryj zaawansowane + Pokaż zaawansowane + Nie można znaleźć właściwego serwera domowego. Zweryfikuj swój identyfikator + To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \"@user:homeserver.org\" + Jeżeli nie pamiętasz hasła, cofnij się aby je zresetować. + Matrix ID + Jeżeli założyłeś(-łaś) konto na serwerze domowym, użyj swojego Matrix ID (np. @user:domain.com) i hasła poniżej. + Zaloguj z Identyfikatorem Matrix (Matrix ID) + Zaloguj z Identyfikatorem Matrix (Matrix ID) + Alternatywnie, jeżeli już masz konto i znasz swój identyfikator Matrix (Matrix ID) oraz hasło, możesz użyć tej metody: + Ten serwer domowy pracuje na starej wersji. Poproś jego administratora o zaktualizowanie go. Możesz kontynuować, ale niektóre funkcjonalności mogą nie działać poprawnie. + Użyj proszę formatu międzynarodowego (numer telefonu musi zaczynać się od \"+\") + Wpisz adres serwera, którego chcesz używać + Zrobiłeś(-łaś) to dostępne tylko przez zaproszenie + Uczyniłeś(-łaś) ten pokój dostępnym tylko poprzez zaproszenie. + Uczyniłeś(-łaś) ten pokój publicznym dla każdego kto zna link. + Nie dokonano żadnych zmian + Usuń z niskiego priorytetu + Dodaj do niskiego priorytetu + Usuń z ulubionych + Dodaj do ulubionych + Nie ma żadnych plików w tym pokoju + %1$s o %2$s + PLIKI + Nie ma żadnych multimediów w tym pokoju + %1$d z %2$d + Obróć i przytnij + Dodaj obraz z + Utwórz nową konwersację bezpośrednią poprzez skanowanie kodu QR + Utwórz nową konwersację bezpośrednią poprzez Matrix ID + Niepoprawny kod weryfikacyjny. + Kod + Czy akceptujesz wysłanie informacji o Twoich kontaktach numerów telefonu i/lub adresów e-mail) do skonfigurowanego Serwera Tożsamości (%1$s) w celu odkrycia istniejących osób, które znasz\? +\n +\nW celu zapewnienia większej prywatności, wysłane dane zostaną poddane operacji haszowania przed wysłaniem. + Wyślij adresy e-mail oraz numery telefonów + Udziel zgody + Wycofaj moją zgodę + Nie udzieliłeś zgody na wysłanie adresów e-mail oraz numerów telefonów do tego serwera tożsamości w celu odkrycia innych użytkowników z Twoich kontaktów. + Udzieliłeś zgody na wysłanie adresów e-mail oraz numerów telefonów do tego serwera tożsamości w celu odkrycia innych użytkowników z Twoich kontaktów. + Wyślij adresy e-mail oraz numery telefonów + Wysłaliśmy do Ciebie wiadomość potwierdzającą na %s, sprawdź najpierw pocztę i kliknij w link potwierdzający + Sugestie + Kontakty + Znani użytkownicy + Ostatnie + Kod QR + Dodaj poprzez kod QR + Dodaj dedykowaną kartę dla nieprzeczytanych powiadomień na ekranie głównym. + Szukaj poprzez imię bądź ID + Pokazuj całą historię w zaszyfrowanych pokojach + Ten pokój został utworzony ale niektóre zaproszenia nie zostały wysłane z następującego powodu: +\n +\n%s + Ustawienia pokoju + Temat + Temat pokoju (opcjonalnie) + Nazwa pokoju + Tego pokoju nie można podejrzeć. Czy chcesz do niego dołączyć\? + Ten pokój nie jest dostępny w tej chwili. +\nSpróbuj ponownie później bądź zapytaj administratora czy masz stosowne uprawnienia. + Pokaż symbol zastępczy dla usuniętych wiadomości + Pokaż usunięte wiadomości + Wiadomość usunięta + Ustaw bezpieczną kopię zapasową + Zabezpieczenie przeciwko utracie dostępu do zaszyfrowanych wiadomości oraz danych + Klucz odzyskiwania został zapisany. + Brak aktywnych widżetów + Zarządzaj integracjami + %1$s i %2$s + %1$s w %2$s i %3$s + + %d zaproszenie + %d zaproszenia + %d zaproszeń + %d zaproszeń + + + %1$d/%2$d klucz zaimportowano pomyślnie. + %1$d/%2$d klucze zaimportowano pomyślnie. + %1$d/%2$d kluczy zaimportowano pomyślnie. + %1$d/%2$d kluczy zaimportowano pomyślnie. + + Klucze pomyślnie wyeksportowane + + %d zablokowany użytkownik + %d zablokowanych użytkowników + %d zablokowanych użytkowników + %d zablokowanych użytkowników + + Opublikować ten pokój dla wszystkich w katalogu pokoi %1$s\? + Cofnij publikację tego adresu + Opublikuj ten adres + Dodaj adres lokalny + Ten pokój nie ma adresu lokalnego + Ustaw adres dla tego pokoju tak aby użytkownicy mogli go znaleźć poprzez Twój serwer domowy (%1$s) + Adres Lokalny + Nowy adres publiczny (np. #alias:server) + Brak innych opublikowanych adresów. + Nie opublikowano dotąd innych adresów, dodaj nowy poniżej. + Opublikować ten pokój w katalogu pokoi %1$s\? + Usunąć adres \"%1$s\"\? + Cofnąć publikację adresu \"%1$s\"\? + Opublikuj + Opublikuj nowy adres ręcznie + Inne opublikowane adresy: + Główny adres + To jest główny adres + Opublikowane adresy mogą zostać wykorzystane przez kogokolwiek na dowolnym serwerze do dołączenia do Twojego pokoju. Żeby opublikować adres musi być on najpierw ustawiony jako adres lokalny. + Opublikowane adresy + Adresy pokoju + Obejrzyj i zarządzaj adresami tego pokoju oraz jego widocznością w katalogu pokoi. + Adres pokoju + Dostęp do pokoju + Zmiany dotyczące tego kto może czytać historię zostaną zastosowane wyłącznie do przyszłych wiadomości w tym pokoju. Widoczności już istniejącej historii pozostanie niezmieniona. + Zarządzaj adresami e-mail oraz numerami telefonów powiązanymi z Twoim kontem Matrix + Adresy e-mail i numery telefonów + Włącz \"Zezwalaj na integracje\" w Ustawieniach żeby to zrobić. + Integracje są wyłączone + To zastąpi obecny Klucz bądź Hasło. + Wygeneruj nowy Klucz Bezpieczeństwa albo Hasło dla istniejącej kopii zapasowej. + Zabezpiecza przeciwko utracie dostępu do zaszyfrowanych wiadomości oraz danych poprzez zapisanie zaszyfrowanych kluczy na Twoim serwerze. + Zarządzaj + Uwzględnij wydarzenia związane z zaproszeniem/dołączeniem/opuszczeniem/wykopaniem/zbanowaniem oraz zmiany wyświetlanego awatara/pseudonimu. + Powiadomienie zostało kliknięte! + Proszę kliknąć na powiadomieniu, Jeżeli nie widzisz powiadomienia, sprawdź ustawienia systemowe. + Widzisz powiadomienia! Kliknij na mnie! + Nie udało się odebrać push. Rozwiązaniem może być reinstalacja aplikacji. + Aplikacja oczekuje na PUSH + Upewnij się, że kliknąłeś w link w wiadomości e-mail, którą do Ciebie wysłaliśmy. + Usunąć %s\? + Numery telefonu + Żaden adres e-mail nie został dodany do Twojego konta + Adres e-mail + Nie dodano żadnego numeru telefonu do Twojego konta + Wyszukiwanie w pokojach stosujących szyfrowanie nie jest obecnie wspierane. + Filtruj zbanowanych użytkowników + Odbanowanie użytkownika pozwoli mu na ponowne dołączenie do pokoju. + Zbanuj użytkownika + Powód wykopania + Wykop użytkownika + Czy na pewno anulować zaproszenie dla tego użytkownika\? + Anuluj zaproszenie + Zaprzestanie ignorowania użytkownika spowoduje ponowne wyświetlanie wszystkich jego wiadomości. + Przestań ignorować użytkownika + Zignorowanie tego użytkownika usunie wszystkie jego wiadomości z pokoi, które współdzielicie. +\n +\nOperacja ta może zostać cofnięta w dowolnej chwili poprzez ustawienia ogólne. + Ignoruj użytkownika + Zdegraduj + Po zdegradowaniu się nie będziesz miał możliwości cofnięcia tego procesu, jeżeli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju odzyskanie uprawnień będzie niemożliwe. + Anuluj zaproszenie + Żeby zeskanować kod QR musisz zezwolić na dostęp do aparatu. + Pytaj o potwierdzenie przed rozpoczęciem połączenia + Błąd SSL. + Błąd SSL: tożsamość peer-a nie została zweryfikowana. + Ten numer telefonu jest już zdefiniowany. + Włącz HD + Wyłącz HD + Tył + Przód + Bezprzewodowy zestaw słuchawkowy + Zestaw słuchawkowy + Głośnik + Telefon + Nie udało się zestawić połączenia czasu rzeczywistego. +\nPoproś administratora Twojego serwera domowego o skonfigurowanie serwera TURN w celu zapewnienia poprawnego dziania połączeń. + Koniec wyników + Powiadomienia + Sukces + Śledzenie błędów + Skopiuj do swojego magazynu w chmurze + Zapisz w pamięci USB bądź na dysku zapasowym + Wykorzystaj ten %1$s jako zabezpieczenie na wypadek utraty %2$s. + Konfigurowanie odzyskiwania. + Nie zweryfikujesz %1$s (%2$s) jeżeli przerwiesz w tym momencie. Zacznij ponownie w ich profilu użytkownika. + ROZUMIEM + Zapisz swój Klucz Bezpieczeństwa + Fraza Bezpieczeństwa + Ustaw Frazę Bezpieczeństwa + Wybierz nazwę użytkownika. + Przepraszamy, ta operacja nie jest jeszcze dostępna dla kont wykorzystujących Single Sign-On. + Oznacz jako Zaufane + Potwierdź swoją tożsamość poprzez zweryfikowanie tego logowania aby uzyskać dostęp do zaszyfrowanych wiadomości. + Potwierdź swoją tożsamość poprzez zweryfikowanie tego logowania przy pomocy którejś z pozostałych sesji w celu przyznania dostępu do zaszyfrowanych wiadomości. + Interaktywna weryfikacja z wykorzystaniem emotikon + Zweryfikuj logowanie + Zweryfikuj nowe logowanie do swojego konta: %1$s + Sprawdź wszystkie swoje sesje żeby upewnić się, że Twoje konto oraz wiadomości są bezpieczne + Sprawdź gdzie jesteś zalogowany(-na) + Zaszyfrowane przez niezweryfikowane urządzenie + Niezaszyfrowane + + Pokaż urządzenie które możesz wykorzystać do weryfikacji + Pokaż %d urządzenia które możesz wykorzystać do weryfikacji + Pokaż %d urządzeń które możesz wykorzystać do weryfikacji + Pokaż %d urządzeń które możesz wykorzystać do weryfikacji + + Zaczniesz ponownie od zera, bez historii, bez wiadomości, bez zaufanych urządzeń bądź użytkowników + Jeżeli zresetujesz wszystko + Wykonaj tę akcję wyłącznie wówczas gdy nie masz żadnego innego urządzenia na którym możesz zweryfikować bieżące urządzenie. + Zresetuj wszystko + Zapomniałeś(-łaś) albo straciłeś(-łaś) wszystkie opcje odzyskiwania\? Zresetuj wszystko + Nie udało się uzyskać dostępu do bezpiecznego magazynu + Kopia zapasowe nie mogła być odszyfrowana z wykorzystaniem tego Klucza Odzyskiwania: zweryfikuj, czy wprowadziłeś(-łaś) poprawny klucz. + Sprawdzanie klucza kopii zapasowej + Aktualizacja szyfrowania jest dostępna + Kiedy pokoje są aktualizowane + Zabezpiecz i odblokuj zaszyfrowane wiadomości oraz zaufane poprzez %s. + Naklejka + %1$s zrobił(a) to dostępne tylko z zaproszeniem. + + %1$s, %2$s i %3$d czyta + %1$s, %2$s i %3$d czytają + + + + Nie udało się uzyskać widoczności katalogu bieżącego pokoju (%1$s). + Skonfiguruj na tym urządzeniu + Czy chcesz się zdegradować\? + Zezwól na dostęp do Twoich kontaktów. + Wybierz urządzenie dźwiękowe + Połączenie Element nieudane + Zrezygnuj + Rozpocznij konwersację + Łącze Matrix + Odrzuć zmiany + Istnieję niezachowane zmiany. Czy chcesz je odrzucić\? + Ten pokój nie został jeszcze utworzony. Czy chcesz anulować tworzenie pokoju\? + Ten link jest niepoprawny + Kod QR nie został zeskanowany! + Nieprawidłowy kod QR (nieprawidłowe URI)! + Nie można wysłać wiadomości bezpośredniej do samego siebie! + Nie można odnaleźć tego pokoju. Upewnij się, że istnieje. + Nie można otworzyć pokoju w którym zostałeś zablokowany. + Potwierdź PIN aby zablokować kod PIN + Zmień swój bieżący kod PIN + Zmień kod PIN + Kod PIN jest wymagany za każdym razem kiedy otwierasz Element. + Kod PIN jest wymagany po dwóch minutach nieużywania Element. + Wymagaj kodu PIN po upływie dwóch minut + Wyświetlaj tylko liczbę nieprzeczytanych wiadomości w prostym powiadomieniu. + Pokazuj szczegóły takie jak nazwa pokoju lub treść wiadomości. + Pokazuj treść w powiadomieniach + Kod PIN jest jedynym sposobem na odblokowanie Element. + Włącz specyficzne dla urządzenia funkcje biometryczne takie jak czytnik odcisków palców bądź rozpoznawanie twarzy. + Włącz biometrię + Jeżeli chcesz zresetować kod PIN, naciśnij Zapomnij kod PIN aby wylogować i zresetować. + Włącz kod PIN + Skonfiguruj ochronę + Ochrona dostępu poprzez kod PIN oraz biometrię. + Ochrona dostępu + Aby zresetować kod PIN musisz się ponownie zalogować i utworzyć nowy. + Nowy kod PIN + Zresetuj kod PIN + Zapomniałeś(-łaś) kodu PIN\? + Wprowadź Twój kod PIN + Nie udało się potwierdzić kodu PIN, proszę wprowadzić nowy. + Potwierdź kod PIN + Dla bezpieczeństwa wybierz kod PIN + Zbyt wiele błędnych prób, zostałeś(-łaś) wylogowany(-na) + Ostrzeżenie! Pozostała ostatnia próba przed wylogowaniem! + + Zły kod, pozostała %d próba + Zły kod, pozostały %d próby + Zły kod, pozostało %d prób + Zły kod, pozostało %d prób + + Wpisz tajną Frazę która jest znana jedynie Tobie i wygeneruj klucze do kopii zapasowej. + Wygeneruj klucz bezpieczeństwa do przechowywania w bezpiecznym miejscu takim jak menadżer haseł lub sejf. + Twój serwer domowy (%1$s) proponuje użycie %2$s jako serwera tożsamości + Użytkownik nie udzielił zgody. + Obecnie brak powiązania z tym identyfikatorem. + Powiązanie nieudane. + W trosce o Twoją prywatność, Element obsługuje jedynie wysłanie skrótów (hash) adresów e-mail oraz numerów telefonu. + Zaakceptuj najpierw reguły serwera tożsamości w ustawieniach. + Najpierw skonfiguruj serwer tożsamości. + Ta operacja nie jest możliwa. Ten serwer domowy jest przestarzały. + Ten serwer tożsamości jest przestarzały. Element obsługuje jedynie API V2. + Rozłączyć z serwerem tożsamości %s\? + Otwórz warunki %s + Ładowanie dostępnych języków… + Inne dostępne języki + Bieżący język + Podziel się tym kodem z innymi ludźmi tak aby mogli go zeskanować, dzięki czemu będą mogli Ciebie dodać i rozpocząć konwersację. + Mój kod + Udostępnij mój kod + Zeskanuj kod QR + Nie możemy zaprosić użytkowników. Zweryfikuj osoby, które chcesz zaprosić i spróbuj ponownie. + + Zaproszenia wysłane do %1$s i jeszcze jednej osoby + Zaproszenia wysłane do %1$s i %2$d innych osób + Zaproszenia wysłane do %1$s i %2$d innych osób + Zaproszenia wysłane do %1$s i %2$d innych osób + + To nie jest prawidłowy kod QR Matrix + Zaproszenia wysłane do %1$s i %2$s + Zaproszenie wysłane do %1$s + 🔐️ Dołącz do mnie na Element + Cześć, pogadaj ze mną na Element: %s + Zaproś przyjaciół + Zaproś użytkowników + Zapraszanie użytkowników… + ZAPROŚ + Dodaj ludzi + Dodaj członków + Nie mogliśmy utworzyć Twojej wiadomości bezpośredniej. Sprawdź użytkownika, któremu chcesz wysłać zaproszenie i spróbuj ponownie. + Link %1$s kieruje do innej strony: %2$s. +\n +\nCzy na pewno kontynuować\? + Kliknij dwukrotnie w ten link + Wybierz hasło. \ No newline at end of file diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index 65db55c162..f5362d229a 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -507,7 +507,7 @@ \'%s\' não é um formato válido para um alias Você não terá endereço principal especificado para esta sala. Alertas do endereço principal - Definir como Endereço Principal + Definir como endereço principal Retirar este endereço como principal Copiar o ID desta sala Copiar o endereço desta sala @@ -1375,9 +1375,9 @@ Boas-vindas! Leia mensagens não lidas aqui Conversas - Suas conversas serão exibidas aqui + Suas conversas serão exibidas aqui. Toque no botão + abaixo para conversar com alguém. Salas - Seus salas serão exibidas aqui + Seus salas serão exibidas aqui. Toque no botão + abaixo para pesquisar as salas existentes ou criar novas. Reações Concordo Curtir @@ -2309,4 +2309,37 @@ Aceite a permissão para acessar seus contatos. Para escanear um código QR, você precisa permitir o acesso à câmera. Começar a conversar + Tornar público este endereço + Adicionar um endereço local + Esta sala não tem endereços locais + Endereços locais + Remover o endereço \"%1$s\"\? + Publicar + Publicar um novo endereço manualmente + Outros endereços públicos: + Endereço principal + Este é o endereço principal + Os endereços públicos podem ser usados por qualquer pessoa em qualquer servidor para entrar na sua sala. Para tornar público um endereço, primeiramente ele precisa ser definido como um endereço local. + Endereços públicos + Endereços da sala + Veja e gerencie os endereços desta sala e a visibilidade dela na lista de salas. + Endereços da sala + Adicionar + Alterar o seu PIN atual + Alterar o PIN + Esta sala não pode ser visualizada. Você quer entrar nela\? + Esta sala não está acessível no momento. +\nTente novamente mais tarde, ou peça ao administrador da sala para verificar se você tem acesso. + Não foi possível saber a visibilidade atual da sala na lista de salas (%1$s). + Publicar esta sala na lista pública de salas de %1$s\? + Remover este endereço + Defina endereços para esta sala, tendo em vista que as pessoas possam encontrá-la por meio do servidor local (%1$s) + Novo endereço publicado (por exemplo, #apelido:servidor) + Nenhum outro endereço publicado ainda. + Nenhum outro endereço publicado ainda, adicione um abaixo. + Tornar pública esta sala na lista de salas de %1$s\? + Remover o endereço \"%1$s\"\? + Acesso à sala + Alterar quem pode ler o histórico só se aplicará às futuras mensagens nesta sala. A visibilidade do histórico existente não será alterada. + Remover \ No newline at end of file diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 7716955d23..273d6b5771 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -198,7 +198,7 @@ Вчера Сегодня - Название Комнаты + Название комнаты Тема комнаты Вызов соединён @@ -416,7 +416,7 @@ Сессии Информация о сессии ID - Общеизвестное имя + Публичное имя Обновить публичное имя Последнее подключение %1$s @ %2$s @@ -1268,9 +1268,9 @@ Добро пожаловать домой! Узнайте больше о непрочитанных сообщениях здесь Беседа - Здесь будут отображаться ваши диалоги + Здесь будут отображаться ваши диалоги. Нажмите + внизу справа, чтобы начать. Комнаты - Здесь будут отображаться ваши комнаты + Здесь будут отображаться ваши комнаты. Коснитесь + внизу справа, чтобы найти существующие или создать свои. Реакции Принять Нравиться @@ -1295,7 +1295,7 @@ Новая комната СОЗДАТЬ Имя - Публичные + Публичная Любой сможет присоединиться к этой комнате Каталог номеров Опубликовать эту комнату в каталоге номеров @@ -1612,7 +1612,7 @@ Настройки Текущая сессия Другие сессии - Включено шифрование + Включить шифрование Недоверенный вход Вложения Интерактивная проверка со смайлами @@ -2300,7 +2300,7 @@ Добавить к низкому приоритету Добавить изображение из Тема - Название Комнаты + Название комнаты Вы дали свое согласие на отправку электронных писем и телефонных номеров на этот сервер идентификации для обнаружения других пользователей из ваших контактов. Добавить по QR-коду Поиск по имени или идентификатору @@ -2360,4 +2360,37 @@ Создать новый диалог по Matrix ID Отправить электронную почту и номера телефонов Отправить электронную почту и номера телефонов + Изменить текущий PIN-код + Изменить PIN-код + Предварительный просмотр этой комнаты невозможен. Вы хотите к ней присоединиться\? + Доступ в эту комнату в настоящее время закрыт. +\nПовторите попытку позже или попросите администратора комнаты проверить, есть ли у вас доступ. + Не удалось получить текущую видимость каталога комнаты (%1$s). + Опубликовать эту комнату для всех в каталоге комнат %1$s\? + Отменить публикацию этого адреса + Опубликовать этот адрес + Добавить локальный адрес + У этой комнаты нет локальных адресов + Задайте адреса для этой комнаты, чтобы пользователи могли найти эту комнату через ваш домашний сервер (%1$s) + Локальные адреса + Новый опубликованный адрес (например, #alias:server) + Других опубликованных адресов пока нет. + Других опубликованных адресов пока нет, добавьте первый ниже. + Опубликовать эту комнату для всех в каталоге комнат %1$s\? + Удалить адрес \"%1$s\"\? + Отменить публикацию адреса \"%1$s\"\? + Опубликовать + Опубликовать новый адрес вручную + Другие опубликованные адреса: + Основной адрес + Это основной адрес + Опубликованные адреса могут быть использованы кем угодно на любом сервере, чтобы присоединиться к вашей комнате. Чтобы опубликовать адрес, сначала его нужно настроить как локальный. + Опубликованные адреса + Адреса комнаты + Просматривайте и управляйте адресами этой комнаты, а также её видимостью в каталоге комнат. + Адреса комнаты + Доступ в комнату + Изменение того, кто может читать историю, будет применяться только к будущим сообщениям в этой комнате. Видимость существующей истории не изменится. + Отменить публикацию + Добавить \ No newline at end of file diff --git a/vector/src/main/res/values-sl/strings.xml b/vector/src/main/res/values-sl/strings.xml index d491fb8b86..bc7fbebe14 100644 --- a/vector/src/main/res/values-sl/strings.xml +++ b/vector/src/main/res/values-sl/strings.xml @@ -6,5 +6,5 @@ Ponvno pošlji Pošlji Sinhroniziram… - ZDA + SI \ No newline at end of file diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml index 9be2118399..50dc12fced 100644 --- a/vector/src/main/res/values-sq/strings.xml +++ b/vector/src/main/res/values-sq/strings.xml @@ -469,8 +469,8 @@ \'%s\' s’është format i vlefshëm aliasesh S’do të keni adresë kryesore të caktuar për këtë dhomë. Sinjalizime adrese kryesore - Caktoje si Adresë Kryesore - Hiqe Nga Adresë Kryesore + Caktoje si adresë kryesore + Hiqe nga adresë kryesore Kopjo ID Dhome Kopjo Adresë Dhome Fshehtëzimi në këtë dhomë është i aktivizuar. @@ -1164,9 +1164,9 @@ Mirë se vini në vatër! Mbaroni punë me mesazhet e palexuara Biseda - Biseda përmes mesazhesh të drejtpërdrejta do të shfaqen këtu + Biseda përmes mesazhesh të drejtpërdrejta do të shfaqen këtu. Prekni + poshtë djathtas, që të nisni një të tillë. Dhoma - Dhomat tuaja do të shfaqen këtu + Dhomat tuaja do të shfaqen këtu. Prekni + poshtë djathtas që të gjeni të tilla ekzistuese ose që të nisni një tuajën. Reagime Pajtohem E pëlqej @@ -2236,4 +2236,40 @@ Që të skanoni një kod QR, lypset të lejoni përdorim kamere. Filloni të Llafoseni Jepni leje për hyrje te kontaktet tuaja. + Kufje dhe mikrofon pa fill + Kufje dhe mikrofon + Ndryshoni PIN-in tuaj të tanishëm + Ndryshoni PIN-in + Së fundi + S’mund të bëhet paraparje e kësaj dhome. Doni të hyni\? + Te kjo dhomë s’hyhet dot tani. +\nRiprovoni më vonë, ose kërkojini një përgjegjësi dhome të kontrollojë nëse keni leje për hyrje. + S’arrihet të merret dukshmëria për listën e tanishme të dhomave (%1$s). + Të bëhet publike kjo dhomë te publiket në listën e dhomave të %1$s\? + Hiqe këtë adresë nga publike + Bëje publike këtë adresë + Shtoni një adresë vendore + Kjo dhomë s’ka adresa vendore + Ujdisni adresa për këtë dhomë, që kështu përdoruesit të mund ta gjejnë këtë dhomë përmes shërbyesit tuaj Home (%1$s) + Adresa Vendore + Adresa të reja të bëra publike (p.sh., #alias:server) + Ende pa adresa të tjera të bëra publike. + Ende pa adresa të tjera të bëra publike, shtoni një më poshtë. + Të bëhet publike kjo dhomë te lista e dhomave të %1$s\? + Të fshihet adresa \"%1$s\"\? + Të hiqet nga publike adresa \"%1$s\"\? + Bëje publike + Publikoni dorazi një adresë të re + Adresa të tjera të bëra publike: + Adresë kryesore + Kjo është adresa kryesore + Adresat e publikuara mund të përdoren nga cilido, në cilindo shërbyes, për të hyrë në dhomën tuaj. Që të bëni publike një adresë, lypset të ujdiset së pari si një adresë vendore. + Adresa të Publikuara + Adresa Dhome + Shihni dhe administroni adresa të kësaj dhome, dhe dukshmërinë e saj te lista e dhomave. + Adresa dhome + Leje mbi dhomën + Ndryshimet se cili mund të lexojë historikun do të aplikohen vetëm për mesazhe të ardhshëm në këtë dhomë. Dukshmëria e historikut ekzistues do të mbesë e pandryshuar. + Hiqi botimin + Shto \ No newline at end of file diff --git a/vector/src/main/res/values-sv/strings.xml b/vector/src/main/res/values-sv/strings.xml index f5a848f819..8c83a30c94 100644 --- a/vector/src/main/res/values-sv/strings.xml +++ b/vector/src/main/res/values-sv/strings.xml @@ -427,7 +427,7 @@ Du är ikapp! Du har inga olästa meddelanden kvar Rum - Dina rum kommer att visas här + Dina rum kommer att visas här. Tryck på + nere till höger för att hitta existerande eller starta några egna. Skapa ett nytt rum Rum Direktmeddelanden @@ -888,7 +888,7 @@ Nya säkra meddelandenycklar Den här sessionen fick ett oväntat meddelande Ett ogiltigt meddelande mottogs - Dina direktmeddelandekonversationer kommer att visas här + Dina direktmeddelandekonversationer kommer att visas här. Tryck på + nere till höger för att starta några. Meddelande raderat Importera krypteringsnycklar från filen \"%1$s\". Krypterar fil… @@ -2191,4 +2191,92 @@ Direktmeddelande Skicka historik över nyckeldelningsförfrågningar Inga fler resultat + Ge tillstånd att komma åt dina kontakter. + För att skanna en QR-kod så behöver du ge åtkomst till kameran. + Avpublicera + Lägg till + Börja chatta + Matrix-länk + QR-kod inte skannad! + Ogiltig QR-kod (ogiltig URI)! + Kan inte DMa dig själv! + Dela med text + Ändra din nuvarande PIN-kod + Ändra PIN-kod + Sök efter kontakter på Matrix + Sätt avatar + Användarsamtycket har inte getts. + Dela den här koden med folk så att de kan skanna den för att lägga till dig och börja chatta. + Min kod + Dela min kod + Skanna en QR-kod + Det är inte en giltig Matrix-QR-kod + 🔐️ Gå med mig i Element + Hallå, prata med mig i Element: %s + Bjud in vänner + Lägg till personer + "Ämne: " + Lägg till ett ämne + %s för att låta personer veta vad det här rummet handlar om. + Det här är början av din direktmeddelandehistorik med %s. + Det här är början av konversationen. + Det här är början av %s. + Du har inte behörighet att aktivera kryptering i det här rummet. + Skapar rum… + Vissa tecken tillåts inte + Vänligen ange en rumsadress + Den här adressen används redan + Rumsadress + Du kanske vill aktivera detta om rummet bara kommer att användas för samarbete med interna team på din hemserver. Detta kan inte ändras senare. + Blockera alla som inte är en del av %s från att någonsin gå med i det här rummet + Dölj avancerat + Visa avancerat + %1$d av %2$d + Skapa en ny direktkonversation genom att skanna en QR-kod + Skapa en ny direktkonversation med Matrix-ID + För att kunna upptäcka existerande kontakter du känner, accepterar du att skicka din kontaktdata (telefonnummer och/eller e-postadresser) till den konfigurerade identitetsservern (%1$s)\? +\n +\nFör högre sekretess så kommer datan att hashas innan den skicka. + Skicka e-postadresser och telefonnummer + Ge samtycke + Återkalla mitt samtycke + Du har inte gett samtycke att skicka e-postadresser och telefonnummer till den här identitetsservern för att upptäcka andra användare baserat på dina kontakter. + Du har gett samtycke att skicka e-postadresser och telefonnummer till den här identitetsservern för att upptäcka andra användare baserat på dina kontakter. + Skicka e-postadresser och telefonnummer + Förslag + Kontakter + Kända användare + Senaste + QR-kod + Lägg till med QR-kod + Sök med namn eller ID + Det här rummet kan inte förhandsgranskas. Vill du gå med i det\? + Det här rummet är inte åtkomligt just nu. +\nFörsök igen senare, eller be en rumsadministratör för att kolla om du har åtkomst. + Kunde inte hämta nuvarande rumskatalogssynlighet (%1$s). + Publicera det här rummet för offentligheten i rumskatalogen för %1$s\? + Avpublicera den här adressen + Publicera den här adressen + Lägg till en lokal adress + Det här rummet har inga lokala adresser + Sätt adresser för det här rummet så att användare kan hitta det här rummet via din hemserver (%1$s) + Lokala adresser + Nya publicerade adresser (t.ex. #alias:server) + Inga andra publicerade adresser än. + Inga andra publicerade adresser än, lägg till en nedan. + Publicera den här rummet till offentligheten i rumskatalogen för %1$s\? + Radera adressen \"%1$s\"\? + Avpublicera adressen \"%1$s\"\? + Publicera + Publicera en ny adress manuellt + Andra publicerade adresser: + Huvudadress + Detta är huvudadressen + Publicerade adresser kan användas av vem som helst på vilken server som helst för att gå med i ditt rum. För att publicera en adress så måste den vara satt som en lokal adress först. + Publicerade adresser + Rumsadresser + Se och hantera adresser för det här rummet, och dess synlighet i rumskatalogen. + Rumsadresser + Rumsåtkomst + Ändringar av vilka som kan läsa historik kommer bara gälla för framtida meddelanden i det här rummet. Synligheten för existerande historik kommer att vara oförändrad. \ No newline at end of file diff --git a/vector/src/main/res/values-szl/strings.xml b/vector/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..41a3680054 --- /dev/null +++ b/vector/src/main/res/values-szl/strings.xml @@ -0,0 +1,66 @@ + + + Zawrzij + Strzim + Ôdtwōrz + Aktywne połōnczynie + Zgłoś zawartość + Rozłōncz + Ôdkoż + Brak + Przemianuj + Skasuj + Pokoż ôdszyfrowane zdrzōdło + Pokoż zdrzōdło + Bezpostrzedni link + Przekoż + Niyskorzij + Wymaż + Godej + Udostympnij + Pobier + Cytuj + Wymaż + Wyślij zaś + Wyślij + Ôstōń + Pociep + Spamiyntej + Pociep + OK + Wgrowanie… + Licyncyje podmiotōw trzecich + Stracisz dostymp do zaszyfrowanych wiadōmości, chyba że wykōnosz ibryczno kopijo kluczy przed ôdlogowaniym sie. + Stwōrz kopijo ibryczno + Je żeś zicher\? + Użyj ibrycznyj kopije klucza + Tworzynie ibrycznyj kopije kluczy… + Niy chca mojich zaszyfrowanych wiadōmości + Coby niy stracić dostympu do swojich zaszyfrowanych wiadōmości, aktywuj ibryczno kopijo klucza na wszyskich aktywnych sesyjach. + Trwo tworzynie ibrycznyj kopije klucza. Jeźli ôdlogujesz sie teroz, to stracisz dostymp do zaszyfrowanych wiadōmości. + Stracisz zaszyfrowane wiadōmości, jeźli sie teroz ôdlogujesz + Ibryczno kopijo kluczy niy ma gotowo, prosza czekać… + Zweryfikuj sesyjo + Użyj ibrycznyj kopije klucza + Ibryczno Kopijo Klucza + Wyślij nalepka + Informacyje ô społeczności + Zgłoś feler + Archiwum + Informacyje ô używoczu + Sztalōnki + Izba + Wiadōmości + Ciche powiadōmiynia + Głośne powiadōmiynia + Nasuchowanie zdarzyń + Synchrōnizowanie… + Inicjalizacyjo usugi + Tymat Status.im + Czorny tymat + Ciymny tymat + Jasny tymat + Latn + PL + pl + \ No newline at end of file diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index ff949f88b5..a298fb6cd3 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -27,7 +27,7 @@ Надіслати ще раз Прибрати Цитата - Поширити + Поділитися Пізніше Переслати Постійне посилання @@ -135,8 +135,8 @@ Пароль Новий пароль Логін - Email адреса - Email адреса (додаткова) + Адреса електронної пошти + Адреса електронної пошти (додаткова) Номер телефону Номер телефону (додатковий) Повторіть пароль @@ -271,13 +271,13 @@ Запросити Залишити цю кімнату Вилучити з цієї кімнати - Забанити - Розбанити + Заблокувати + Розблокувати Зробити звичайним користувачем Зробити модератором Зробити адміністратором - Сховати всі повідомлення користувача - Показати всі повідомлення користувача + Ігнорувати користувача + Перестати ігнорувати ID користувача, ім\'я або email Згадати Показати Список Пристроїв @@ -311,12 +311,12 @@ Довіряти Не довіряти Вийти - Ігнорувати + Нехтувати Відбиток (%s): Не вдалося перевірити сертифікат сервера. Це може означати, що хтось зі злими намірами намагається перехопити ваш трафік або ваш телефон не довіряє сертифікату, наданому віддаленим сервером. Якщо адміністратор сервера сказав цього чекати, переконайтесь, що відбиток нижче збігається з відбитком, наданим ним. - Сертифікат почав відрізнятися від того, якому довіряв ваш телефон. Це ДУЖЕ НЕЗВИЧАЙНО. Наполегливо радимо НЕ ПРИЙМАТИ цей новий сертифікат. + Сертифікат почав відрізнятися від того, якому довіряв ваш телефон. Це ДУЖЕ НЕЗВИЧНО. Наполегливо радимо НЕ ПРИЙМАТИ цей новий сертифікат. Сертифікат змінився з довіреного на недовірений. Сервер міг оновити свій сертифікат. Зв\'яжіться з адміністратором сервера, щоб отримати дійсний відбиток. Приймайте сертифікат лише у випадку збігу відбитку вище з відбитком, оприлюдненим адміністратором сервера. @@ -391,7 +391,7 @@ Запрошення до кімнат Виклики Повідомлення від бота - Запускати при старті системи + Запускати під час завантаження Фонова синхронізація Увімкнути фонову синхронізацію Таймаут синхронізації @@ -520,8 +520,8 @@ \'%s\' не є дійсним форматом псевдоніму Основну адресу для цієї кімнати не вказано. Попередження про адресу - Встановити як Основну Адресу - Видалити як Основну Адресу + Встановити основною адресою + Зробити не основною адресою Копіювати ID кімнати Копіювати Адресу Кімнати У цій кімнаті увімкнено шифрування. @@ -538,13 +538,13 @@ Ключ ідентичності Curve25519 Заявлений ключ відбитка пальця Ed25519 Алгоритм - ID сесії + ID сеансу Помилка розшифрування Інформація про пристрій відправника Назва пристрою - Ім\'я - ID пристрою - Ключ пристрою + Загальнодоступна назва + ID сеансу + Ключ сеансу Перевірка Відбиток пальця Ed25519 Експортувати E2E ключі кімнати @@ -630,7 +630,7 @@ Ваш неперевірений пристрій \'%s\' править ключі шифрування. Почати перевірку Поділитись без перевірки - Ігнорувати запит + Знехтувати запитом Помилка виконання команди Команду %s не розпізнано @@ -659,10 +659,10 @@ Синхронізація… Всі повідомлення (гучно) Всі повідомлення - Тільки упоминания - Без звука + Лише згадки + Без звуку Додати ярлик на головний екран - Конфіденційність сповіщень + Приватність сповіщень Нормальний Відправити наліпку Відправити стікер @@ -681,7 +681,7 @@ %d участників - Користувачів з забороною буде вилучено з цієї кімнати й вони не зможуть приєднатися знову. + Заблокованих користувачів буде вилучено з цієї кімнати й вони не зможуть приєднатися знову. %d нове повідомлення %d нових повідомленя @@ -690,9 +690,9 @@ Обмежена конфіденційність Програма потребує дозвіл на роботу у фоновому режимі - • Повідомлення відправляються через Google Cloud Messaging - • Повідомлення містять тільки метаданні - • Зміст сповіщення був надійно віднайдений просто на домашньому сервері Matrix + • Сповіщення надсилаються через Google Cloud Messaging + • Сповіщення містять лише метадані + • Зміст повідомлення було надійно розміщено на домашньому сервері Matrix Ліцензії сторонніх виробників Завантажити Говорити @@ -904,7 +904,7 @@ +%d %d+ Все одно подзвонити - Копнути + Викинути Причина Попередній перегляд посилань у чаті, у разі якщо Ваш сервер підтримує таку можливість. Надсилати сповіщення про набір повідомлення @@ -925,8 +925,8 @@ Markdown вимкнено. Виклики Використовувати стандартний рингтон Element для вхідних викликів - Рингтон вхідного виклику - Оберіть рингтон для викликів: + Мелодія вхідного виклику + Виберіть мелодію викликів: Прийняти Будь ласка, ознайомтесь та прийміть правила цього серверу: Позначити як прочитане @@ -934,7 +934,7 @@ Запуск сервісу Резервна копія ключа Використати резервну копію ключа - Тут з\'явиться список ваших прямих чатів + Тут з\'явиться список ваших прямих бесід. Торкніться + внизу праворуч щоб почати бесіду. Повідомлення видалено Прямі чати Прямі чати @@ -947,7 +947,7 @@ Повідомлення… Ви не маєте доступу до цього повідомлення Очікуємо повідомлення, це може тривати певний час - Вхідний виклик (%s) + Активний виклик (%s) Не вдається отримати домашній сервер за цією URL-адресою, перевірте його Це недійсна адреса сервера Matrix Ця URL-адреса недоступна, перевірте її @@ -976,7 +976,7 @@ Прийняти Відмовити Огляд - Ігнорувати + Знехтувати Перервати Готово Пропустити @@ -1016,7 +1016,7 @@ Запобігати випадковим викликам Мені не потрібні мої зашифровані повідомлення Скасувати зміни - SSL помилка. + Помилка SSL. Ви не можете здійснити дзвінок із самим собою, дочекайтесь, доки інші учасники приймуть ваше запрошення ФАЙЛИ В цій кімнаті немає медіа @@ -1080,7 +1080,7 @@ Електорнні адреси та номери телефонів Надіслати історію запитів спільного доступу до ключів Стрічка подій - Не прчитані повідомлення + Непрочитані повідомлення Провести пальцем, щоб відповісти у стрічці подій Показувати приховані події у стрічці подій Усунення несправностей @@ -1128,4 +1128,361 @@ Недійсна відповідь виявлення домашнього сервера Налаштуйте свою видимість. Видимість + Не вдалося встановити зв’язок у режимі реального часу. +\nПопросіть адміністратора вашого домашнього сервера налаштувати сервер TURN для надійної роботи викликів. + Element не вдалося здійснити виклик + Попросіть адміністратора вашого домашнього сервера (%1$s) налаштувати сервер TURN для надійної роботи дзвінків. +\n +\nЯк варіант, ви можете спробувати використати загальнодоступний сервер на рівні %2$s, але це буде не так надійно й він надаватиме вашу IP-адресу цьому серверу. Ви також можете керувати цим у налаштуваннях. + Більше немає результатів + Відкликати публікування + Додати + Наради використовують політику безпеки та дозволів Jitsi. Усі люди, які зараз перебувають у кімнаті, побачать запрошення приєднатися під час вашої зустрічі. + Почати спілкування + Додати спеціальну вкладку для непрочитаних сповіщень на головному екрані. + Показувати повну історію зашифрованих кімнат + Дані облікового запису + Інструменти розробника + Запобігати знімкам екрана застосунку + Доступне оновлення шифрування + Довершити налаштування безпеки + Інше + Дізнатись більше + Безпека + Безпека та приватність + Ми раді повідомити, що змінили назву! Ваш застосунок оновлено й ви ввійшли у свій обліковий запис. + Зміну параля ще не завершено. +\n +\nЗупинити змінювання пароля\? + Ви успішно змінили налаштування кімнати + Тепер резервні копії ваших ключів шифрування створюються у фоновому режимі на домашній сервер. Початкове резервне копіювання може тривати кілька хвилин. + Резервне копіювання розпочато + Неочікувана помилка + Ключ відновлення + Створення ключа відновлення за допомогою парольної фрази, цей процес може тривати кілька секунд. + Поділитися ключем відновлення з… + Будь ласка, створіть копію + Стоп + Замінити + Схоже у вас вже є резервна копія ключа налаштування з іншого сеансу. Хочете замінити його тим, який ви створюєте\? + Резервна копія вже існує на вашому HomeServer + Ключ відновлення збережено. + Ключ відновлення збережено до теки «%s». +\n +\nПопередження: цей файл може бути видалено, якщо програму видалено. + Зберегти як файл + Поділитися + Зберегти ключ відновлення + Я створив копію + Готово + Зберігайте ключ відновлення десь дуже надійно, наприклад, у менеджері паролів (або сейфі) + Ваш ключ відновлення — це мережа безпеки — ви можете використовувати його для відновлення доступу до ваших зашифрованих повідомлень, якщо ви забудете свою парольну фразу. +\nТримайте ключ відновлення десь дуже надійно, наприклад, у менеджері паролів (або сейфі) + Створюється резервна копія ключів. + Успішно ! + (Додатково) Налаштування за допомогою ключа відновлення + Або захистіть свою резервну копію за допомогою ключа відновлення, зберігаючи її десь у безпеці. + Створення резервної копії + Встановіть парольну фразу + Ми збережемо зашифровану копію ваших ключів на вашому домашньому сервері. Захистіть свою резервну копію парольною фразою, щоб захистити її. +\n +\nДля максимальної безпеки він повинен відрізнятися від пароля вашого облікового запису. + Захистіть свою резервну копію за допомогою парольної фрази. + Експорт ключів вручну + Почніть використовувати резервне копіювання ключів + Повідомлення в зашифрованих кімнатах захищено наскрізним шифруванням. Тільки ви та одержувачі маєте ключі для читання цих повідомлень. +\n +\nБезпечно створюйте резервні копії ключів, щоб не втратити їх. + Ніколи не втрачайте зашифровані повідомлення + Немає доступного сеансу Matrix + Видаліть парольну фразу, якщо хочете, щоб Element створив ключ відновлення. + Парольна фраза занадто слабка + Введіть парольну фразу + Не знайдено дійсного файлу .apk сервісів Google Play. Сповіщення можуть працювати неправильно. + Введіть ім’я користувача. + Беззвучно + Знехтувати + Запит на розподіл ключів + Поділитися + Перевірити + Неперевірений сеанс запитує ключі шифрування. +\nНазва сеансу: %1$s +\nОстанні відвідини: %2$s +\nЯкщо ви не ввійшли в інший сеанс, знехтуйте цим запитом. + Новий сеанс запитує ключі шифрування. +\nНазва сеансу: %1$s +\nОстанні відвідини: %2$s +\nЯкщо ви не ввійшли в інший сеанс, знехтуйте цим запитом. + Для продовження потрібно прийняти Умови користування цією службою. + Немає активних віджетів + Керувати інтеграціями + Менеджер інтеграції не налаштовано. + Читати захищені DRM засоби масової інформації + Використовувати мікрофон + Використовувати камеру + Заблокувати все + Дозволити + Цей віджет хоче використовувати такі ресурси: + На жаль, конференц-дзвінки з Jitsi не підтримуються на старих пристроях (пристрої з ОС Android нижче 5.0) + Ідентифікатор кімнати + Ідентифікатор віджета + Ваша тема + Ваш ідентифікатор користувача + URL-адреса зображення профілю + Ваше видиме ім\'я + Скасувати доступ для мене + Відкрити в браузері + Перезавантажити віджет + Не вдалося завантажити віджет. +\n%s + Використання може спричинити обмін даними з %s: + За його використання може бути встановлено файли cookie та відбуватися обмін даними з %s: + Цей віджет додав: + Завантажити віджет + Віджет + Активні віджети + ПОДАННЯ + %1$s: %2$s %3$s + %1$s: %2$s + ** Не вдалося надіслати — відкрийте кімнату + Я + Нове запрошення + Нові повідомлення + Кімната + Нова подія + %1$s й %2$s + %1$s в %2$s та %3$s + + %d сповіщення + %d сповіщення + %d сповіщень + %d сповіщень + + + %1$s: %2$d повідомлення + %1$s: %2$d повідомлення + %1$s: %2$d повідомлень + %1$s: %2$d повідомлень + + + %d запрошення + %d запрошення + %d запрошень + %d запрошень + + невідома ip + + %1$d/%2$d ключ успішно імпортовано. + %1$d/%2$d ключі успішно імпортовано. + %1$d/%2$d ключів успішно імпортовано. + %1$d/%2$d ключів успішно імпортовано. + + Керування резервною копією ключів + Відновлення зашифрованих повідомлень + Ключі успішно експортовано + Загальнодоступну назву сеансу бачать люди, з якими ви спілкуєтесь + Загальнодоступна назва (видима людям, з якими спілкуєтесь) + + %d заборонений користувач + %d заборонені користувачі + %d заборонених користувачів + %d заборонених користувачів + + Не вдалося отримати поточну видимість каталогу кімнат (%1$s). + Опублікувати цю кімнату для всіх у каталозі кімнат %1$s\? + Скасувати публікацію цієї адреси + Опублікувати цю адресу + Додати локальну адресу + Кімната не має локальної адреси + Встановіть адреси для цієї кімнати, щоб користувачі могли знаходити цю кімнату через ваш домашній сервер (%1$s) + Локальні адреси + Нова опублікована адреса (наприклад, #alias:server) + Інших опублікованих адрес поки що немає. + Інших опублікованих адрес поки що немає, додайте якусь внизу. + Опублікувати цю кімнату для всіх у каталозі кімнат %1$s\? + Видалити адресу \"%1$s\"\? + Скасувати публікацію адреси \"%1$s\"\? + Опублікувати + Опублікувати нову адресу вручну + Інші опубліковані адреси: + Основна адреса + Це основна адреса + Загальнодоступні адреси може використовувати будь-хто на будь-якому сервері для приєднання до вашої кімнати. Щоб опублікувати адресу спочатку встановіть її локальною адресою. + Загальнодоступні адреси + Адреси кімнат + Перегляньте адреси цієї кімнати та керовані ними, а також їх видимість у каталозі кімнати. + Адреси кімнат + Доступ до кімнати + Зміни щодо тих, хто може читати історію, стосуватимуться лише майбутніх повідомлень у цій кімнаті. Видимість наявної історії залишиться незмінною. + Відтворити звук затвора + Вибрати + Типове джерело медіа + Вибрати + Типове стиснення + Медіа + Додаткові відомості: %s + Під час підтвердження номера телефону сталася помилка. + Паролі не збігаються + Пароль не дійсний + Оновити пароль + Під час підтвердження вашої адреси електронної пошти сталася помилка. + Увімкніть для цього параметр \"Дозволити інтеграцію\" у налаштуваннях. + Інтеграцію вимкнено + Керування інтеграцією + Дозволити інтеграції + Режим збереження даних застосовує певний фільтр, тому оновлення присутності та сповіщення про введення фільтруються. + Надати дозвіл + Для отримання надійних сповіщень Element повинен підтримувати з’єднання у фоновому режимі з незначним споживанням даних. +\nНа наступному екрані вам буде запропоновано дозволити Element завжди працювати у фоновому режимі, погодьтеся. + Фонове з’єднання + Це замінить ваш поточний ключ або фразу. + Створіть новий ключ безпеки або встановіть нову фразу безпеки для наявної резервної копії. + Захистіться від втрати доступу до зашифрованих повідомлень та даних створенням резервної копії ключів шифрування на своєму сервері. + Налаштувати на цьому пристрої + Скинути безпечне резервне копіювання + Налаштувати безпечне резервне копіювання + Керувати + Безпечне резервне копіювання + Включає події запрошення/приєднання/виходу/видалення/заборони та зміни зображень профілю/видимих імен. + Показати стан подій учасників кімнати + Управління ключами криптографії + Використовуйте Менеджер інтеграції для керування ботами, мостами, віджетами та пакетами наклейок. +\nМенеджери інтеграції отримують дані конфігурації та можуть змінювати віджети, надсилати запрошення до кімнати та надавати права від вашого імені. + Інтеграції + + %d секунда + %d секунди + %d секунд + %d секунд + + %s +\nСинхронізацію може бути відкладено залежно від ресурсів (акумулятор) або стану пристрою (режим сну). + Бажаний інтервал синхронізації + Не вдалося оновити налаштування. + Ви не отримуватимете сповіщення про вхідні повідомлення, коли програма перебуває у фоновому режимі. + Немає фонової синхронізації + Element періодично синхронізуватиметься у фоновому режимі в певний час (налаштовується). +\nЦе вплине на використання радіо та акумулятора, з’явиться постійне сповіщення про те, що Element очікує на події. + Оптимізовано для реального часу + Element синхронізується у фоновому режимі так, щоб зберегти обмежені ресурси пристрою (акумулятор). +\nЗалежно від стану ресурсів вашого пристрою, синхронізацію може бути відкладено операційною системою. + Оптимізовано для батареї + Режим фонової синхронізації + Застосунки не потребують з\'єднання з HomeServer у фоновому режимі, це має скоротити споживання батареї + Нехтувати оптимізацією + Якщо користувач залишає пристрій від\'єднаним та нерухомим впродовж певного часу з вимкненим екраном, пристрій переходить у режим дрімання. Це запобігає доступу програм до мережі та відкладає їх завдання, синхронізацію та стандартні сигнали тривоги. + Оптимізація акумулятора не впливає на Element. + Оптимізація акумулятора + Вимкнути обмеження + Фонові обмеження ввімкнено для Element. +\nРобота, яку намагається виконати застосунок, буде агресивно обмежена, доки вона перебуває у фоновому режимі й це може вплинути на сповіщення. +\n%1$s + Фонові обмеження для Element вимкнено. Цю перевірку варто виконувати з використанням мобільних даних (без Wi-Fi). +\n%1$s + Перевірте фонові обмеження + Увімкніть Запуск під час завантаження + Служба не запуститься під час перезавантаження пристрою, ви не отримуватимете сповіщень, доки Element не буде відкрито. + Служба запуститься після перезапуску пристрою. + Запускати під час завантаження + Помилка перезапуску служби + Службу зупинено й перезапущено автоматично. + Автоматичний перезапуск служби сповіщень + Запуск служби + Служба сповіщень не працює. +\nСпробуйте перезапустити програму. + Служба сповіщень працює. + Служба сповіщень + Сповіщення натиснено! + Клацніть на сповіщення. Якщо ви не бачите сповіщення, перевірте налаштування системи. + Показ сповіщень + Ви переглядаєте сповіщення! Клацніть на мене! + Не вдалося отримати push. Рішенням може бути перевстановлення застосунку. + Застосунок отримує PUSH + Застосунок очікує PUSH + Випробувальне надсилання + Не вдалося зареєструвати токен FCM на HomeServer: +\n%1$s + Токен FCM успішно зареєстровано на HomeServer. + Реєстрація токена + Додати обліковий запис + [%1$s] +\nЦя помилка не підконтрольна Element. На телефоні немає облікового запису Google. Відкрийте менеджер облікових записів і додайте обліковий запис Google. + [%1$s] +\nЦя помилка не підконтрольна Element. Це може статися з кількох причин. Можливо все запрацює, якщо ви спробуєте пізніше, ви також можете перевірити, чи не обмежено використання даних для служби Google Play в налаштуваннях системи, чи правильний годинник вашого пристрою, або це може статися в користувацькому ROM. + [%1$s] +\nЦя помилка не підконтрольна Element й за даними Google, вона вказує на те, що на пристрої зареєстровано забагато програм у FCM. Помилка виникає лише у випадках, коли встановлено надзвичайно багато застосунків, тому вона не повинна впливати на звичайного користувача. + Не вдалося отримати токен FCM: +\n%1$s + Токен FCM отримано успішно: +\n%1$s + Токен Firebase + Виправити служби Play + Element використовує сервіси Google Play для доставлення push-сповіщень, але, схоже, його налаштовано неправильно: +\n%1$s + Відкрити Налаштування + Сповіщення вимкнено в налаштуваннях системи. +\nБудь ласка, перевірте налаштування системи. + Одну або кілька перевірок не пройдено, надішліть звіт про помилку, щоб допомогти нам розслідувати це. + Одну або кілька перевірок не пройдено, спробуйте запропоновані виправлення. + Основна діагностика в порядку. Якщо ви й далі не отримуєте сповіщень, надішліть звіт про помилку, щоб допомогти нам розслідувати це. + Важливість сповіщень за подією + Переконайтеся, що ви натиснули посилання в електронному листі, який ми надіслали вам. + Вилучити %s\? + Потрібна автентифікація + Це неможливо зробити за допомогою Element mobile + Підтвердити пароль + Фільтрувати заборонених користувачів + Скасування блокування користувача дозволить їм знову приєднатися до кімнати. + Розблокувати користувача + Причина блокування + Заблокувати користувача + викидання користувачів прибере їх з цієї кімнати. +\n +\nЩоб запобігти їх повторному приєднанню, замість цього слід заблокувати їх. + Причина викидання + Викинути користувача + Дійсно скасувати запрошення для цього користувача\? + Скасувати запрошення + Зняття ігнорування з цього користувача знову покаже всі повідомлення від нього. + Не ігнорувати користувача + Ігнорування цього користувача призведе до видалення його повідомлень з кімнат, якими ви ділитесь. +\n +\nВи можете будь-коли змінити цю дію в загальних налаштуваннях. + Ігнорувати користувача + Понизити + Ви не зможете скасувати цю зміну, оскільки понижуєте свої права, якщо ви останній привілейований користувач у кімнаті, неможливо буде повернути собі привілеї. + Понизитися\? + Додайте сервер ідентифікації у свої налаштування, щоб виконати цю дію. + Дозволити доступ до ваших контактів. + Щоб сканувати QR-код необхідно дозволити доступ до камери. + Повернутися до виклику + Триває відеовиклик… + Використовуватиме %s допоміжним, коли ваш домашній сервер не пропонує такого (вашу IP-адресу буде надана під час виклику) + Дозволити допоміжний сервер викликів + Ваш пристрій використовує застарілий протокол безпеки TLS, вразливий до атак, для вашої безпеки ви не зможете під\'єднатися + Помилка SSL: особу співрозмовника не підтверджено. + Встановіть електронну адресу для відновлення облікового запису. Використовуйте пізніше електронну пошту або телефон, щоб люди, які вас знають, могли знайти вас за нею. + Встановіть електронну адресу для відновлення облікового запису. Використовуйте пізніше електронну пошту або телефон, щоб люди, які вас знають, могли знайти вас за нею. + Встановіть телефон, а пізніше, щоб його могли побачити люди, які вас знають. + Встановіть електронну адресу для відновлення облікового запису, а пізніше, щоб вона була додатковою для пошуку людьми, які вас знають. + Номер телефону (додатковий) + Номер телефону + Без звуку + Лише згадки + Всі повідомлення + Всі повідомлення (гучно) + Ігнорувати користувача + Перестати ігнорувати + Підпис + Алгоритм + Версія + Налаштувати безпечне резервне копіювання + Використати ключ безпеки + Налаштувати + Захистіться від втрати доступу до зашифрованих повідомлень та даних створенням резервної копії ключів шифрування на своєму сервері. + Новий пароль + Увага! + Адреса + Ви можете втратити доступ до своїх повідомлень, якщо вийдете з облікового запису або загубите цей пристрій. + Ви впевнені\? \ No newline at end of file diff --git a/vector/src/main/res/values-vi/strings.xml b/vector/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..5fd780f429 --- /dev/null +++ b/vector/src/main/res/values-vi/strings.xml @@ -0,0 +1,279 @@ + + + Lắc điện thoại để báo cáo lỗi + Có vẻ bạn đang lắc điện thoại một cách tức giận. Bạn có muốn báo cáo lỗi không\? + Miêu tả vấn đề của bạn ở đây + Nếu có thể, vui lòng viết miêu tả bằng tiếng Anh. + Vui lòng miêu tả lỗi. Bạn đã làm gì\? Bạn mong điều gì xảy ra\? Điều gì đã xảy ra\? + Báo lỗi + Gửi ảnh chụp màn hình + Gửi lịch sử yêu cầu chia sẻ khóa + Không có nhóm + Cộng đồng + Mời + + %d người dùng + + Không có phòng + Thư mục phòng + Phòng + Không còn kết quả nào nữa + Lọc danh sách yêu thích + Bỏ qua + Đã có một cuộc hội thoại đang diễn ra! + Không có kết quả nào + Bạn chưa cho phép Element truy cập danh bạ của bạn + Không có cuộc trò chuyện nào + Chỉ những liên hệ Matrix + Thư mục người dùng + Sổ địa chỉ địa phương + Các cuộc trò chuyện + Cảnh báo hệ thống + Ưu tiên thấp + Lời mời + Lọc tên cộng đồng + Lọc tên phòng + Lọc người + Xác nhận + Vô hiệu hóa + Lọc tên phòng + Cộng đồng + Phòng + Người + Yêu thích + Thông báo + Thành công + Lỗi + Cảnh báo + Sao chép vào bộ nhớ tạm + Thêm + VN + vi + Latn + Sao chép + Đóng + Mở + Đánh dấu đã đọc + Trả lời nhanh + Đánh dấu tất cả đã đọc + Tìm toàn bộ + Cuộc gọi bằng video + Cuộc gọi bằng giọng nói + Bạn có chắc mình muốn đăng xuất không\? + Đăng xuất + Hành động + Thoát + Chờ + Từ chối + Đồng ý + Từ chối + Huỷ bỏ + Bỏ qua + Ngoại tuyến + hoặc + Vẫn gọi + Bạn không thể gọi chính mình, hãy chờ người tham gia khác chấp nhận lời mời + Không thể bắt đầu cuộc gọi + Bắt đầu cuộc họp âm thanh + Xong + Đồng ý + Mời + Vẫn gửi + Gọi hội thoại không được hỗ trợ trong phòng chat được mã hoá + Thông tin phiên + Bạn không thể gọi chính mình + Các cuộc họp sử dụng các chính sách về quyền và bảo mật của Jitsi. Tất cả mọi người hiện trong phòng sẽ thấy một lời mời tham gia khi cuộc họp của bạn đang diễn ra. + Bắt đầu một cuộc gặp qua video + Bạn cần quyền mời để bắt đầu cuộc hội thoại trong phòng này + Bạn không có quyền bắt đầu cuộc gọi + Bạn không có quyền bắt đầu cuộc gọi trong phòng này + Bạn không có quyền bắt đầu cuộc gọi hội thoại + Bạn không có quyền bắt đầu cuộc gọi hội thoại trong phòng này + Do bị thiếu một số quyền, hành động này không thể thực hiện. + Do không có một số quyền, một số tính năng có thể không hoạt động… + Không thể bắt đầu cuộc gọi, vui lòng thử lại sau + Video + Giọng nói + Có cuộc gọi đến. +\nTham gia với tư cách %1$s hoặc %2$s + Bắt đầu trò chuyện + Cài lại + Bỏ + Tạm dừng + Chạy + Cuộc gọi đang hoạt động + Báo cáo nội dung + Ngắt kết nối + Rút lại + Trống + Đặt lại tên + Xoá + Xem nguồn đã được giải mã + Xem nguồn + Đường dẫn + Chuyển tiếp + Để sau + Xoá + Nói + Chia sẻ + Tải xuống + Trích + Xoá + Gửi lại + Gửi + Ở lại + Thoát + Lưu + Huỷ + OK + Đang tải… + Giấy phép bên thứ ba + Bạn sẽ mất các tin nhắn được mã hoá trừ khi bạn sao lưu khoá trước khi đăng xuất. + Sao lưu + Bạn có chắc không\? + Sử dụng Sao lưu Khoá + Đang sao lưu khoá… + Tôi không muốn các tin nhắn của tôi được mã hoá + Sao lưu Khoá Bảo mật nên được kích hoạt trên tất cả các phiên để tránh mất các tin nhắn được mã hoá. + Đang sao lưu khoá. Nếu bạn đăng xuất bây giờ bạn sẽ không thể xem các tin nhắn được mã hoá. + Bạn sẽ mất các tin nhắn được mã hoá nếu bạn đăng xuất ngay bây giờ + Quá trình sao lưu khoá chưa hoàn thành, vui lòng chờ… + Xác nhận phiên hoạt động + Sử dụng Sao lưu Khóa + Sao lưu khóa + Gửi nhãn dán + Chi tiết về cộng đồng + Báo lỗi + Lịch sử + Chi tiết các thành viên + Cài đặt + Phòng chat + Tin nhắn + Thông báo có âm thanh + Thông báo yên lặng + Theo dõi sự kiện + Đang đồng bộ hóa… + Đang khởi tạo dịch vụ + Nền đen + Nền tối + Nền sáng + Vui lòng kiểm tra email của bạn để tiếp tục quá trình đăng ký + Quên mật khẩu\? + Mật khẩu không trùng khớp + Token không hợp lệ + Thiếu địa chỉ email hoặc số điện thoại + Thiếu số điện thoại + Thiếu địa chỉ email + Đấy không giống một số điện thoại hợp lệ + Đấy không giống một địa chỉ email hợp lệ + Không có mật khẩu + Mật khẩu quá ngắn (ít nhất 6 ký tự) + Tên người dùng chỉ có thể bao gồm chữ cái, số, dấu chấm, dấu gạch nối và dấu gạch dưới + Tên người dùng hoặc mật khẩu không đúng + Xác nhận mật khẩu mới + Nhập lại mật khẩu + Địa chỉ email + Số điện thoại (không bắt buộc) + Số điện thoại + Địa chỉ email (tùy chọn) + Đặt một email để khôi phục tài khoản. Email và số điện thoại có thể dùng để những người biết bạn tìm thấy bạn. + Đặt một email để khôi phục tài khoản. Email và số điện thoại có thể dùng để những người biết bạn tìm thấy bạn. + Đặt một số điện thoại để khôi phục tài khoản và có thể dùng để những người biết bạn tìm thấy bạn. + Đặt một email để khôi phục tài khoản và có thể dùng để những người biết bạn tìm thấy bạn. + Tên + Mật khẩu mới + Mật khẩu + Email hoặc tên người dùng + Quay về màn hình đăng nhập + Gửi email để đặt lại + Bỏ qua + Tạo tài khoản + Đăng nhập + Xin lỗi, không có ứng dụng nào được tìm thấy có thể hoàn thành hành động này. + tiếp tục với… + Hiện tại bạn không có bộ nhãn dán nào được kích hoạt cả. +\n +\nBạn có muốn thêm không\? + Quay video + Chụp ảnh + Chụp ảnh hoặc quay video + Gửi nhãn dán + Gửi tệp tin + Bật HD + Tắt HD + Sau + Trước + Thay đổi camera + Tai nghe không dây + Tai nghe + Loa + Điện thoại + Chọn thiết bị âm thanh + Cuộc gọi Element thất bại + Đừng hỏi lại tôi + Hãy thử dùng %s + Vui lòng yêu cầu quản trị viên của máy chủ nhà của bạn (%1$s) thiết lập một máy chủ TURN để các cuộc gọi có thể hoạt động […]. +\n +\nBạn cũng có thể thử dùng máy chủ công cộng ở %2$s, nhưng cách này sẽ không […] bằng, và địa chỉ IP của bạn cũng sẽ được chia sẻ đến server đó. Bạn có thể quản lý việc này trong mục Cài đặt. + Cuộc gọi thất bại do thiết lập máy chủ sai + Bạn có chắc bạn muốn bắt đầu một cuộc gọi video\? + Bạn có chắc bạn muốn bắt đầu một cuộc gọi bằng giọng nói\? + Bạn có chắc bạn muốn bắt đầu một cuộc trò chuyện mới với %s\? + Gửi giọng nói + Bắt đầu cuộc gọi video + Bắt đầu cuộc gọi bằng giọng nói + Bắt đầu cuộc trò chuyện mới + Tìm + URL máy chủ định danh + Đăng xuất + Đăng nhập + Tạo tài khoản + Tên người dùng + Vào phòng + Đã đọc + Gửi báo cáo lỗi thất bại (%s) + Bản báo cáo lỗi đã được gửi thành công + Tên người dùng này đã được người khác sử dụng + JSON không hợp lệ + Tên/mật khẩu sai + Thiết bị của bạn đang dùng một giao thức TLS lỗi thời, dễ bị tấn công, vì lý do bảo mật, bạn sẽ không thể kết nối + Lỗi SSL. + Lỗi SSL: danh tính của đối tác chưa được kiểm chứng. + Đây không phải là một địa chỉ máy chủ Matrix hợp lệ + Không kết nối được với địa chỉ này, vui lòng kiểm tra lại + Không thể tạo tài khoản mới + Không thể tạo tài khoản mới: Lỗi mạng + Không thể đăng nhập + Không thể đăng nhập: Lỗi mạng + URL phải bắt đầu với http[s]:// + Tôi đã xác nhận địa chỉ email này + Máy chủ định danh: + Máy chủ chính: + Thiết lập kết nối thời gian thực thất bại. +\nXin vui lòng yêu cầu quản trị viên máy chủ nhà của bạn thiết lập máy chủ TURN để có thể gọi điện bình thường. + Trang đầu + Cuộc gọi đang được kết nối… + Cuộc gọi đã được kết nối + Gọi + Chọn nhạc chuông: + Nhạc chuông cho cuộc gọi đến + Dùng nhạc chuông mặc định cho cuộc gọi đến + Yêu cầu xác nhận trước khi gọi + Tránh gọi nhầm + Chủ đề của phòng + Tên phòng + Hôm nay + Chú ý! + Kệ + Bỏ qua đề xuất này + Chia sẻ + Chia sẻ, không kiểm chứng + Kiểm chứng + Bắt đầu kiểm chứng + Máy chủ định danh chưa được cài đặt. + Chương trình đã gặp sự cố lần trước. Bạn có muốn mở trang tường thuật sự cố không\? + Tiến độ (%s%%) + Gửi bản tường thuật sự cố + Gửi bản tường thuật + Gửi + \ No newline at end of file diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index 4c89c5a26f..114519505e 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -1333,8 +1333,8 @@ 您已经跟上了! 您没有未读消息 从这里跟上未读消息 - 您的私聊消息将在此处显示 - 您的聊天室将在此显示 + 您的私聊消息将显示在此处。点击右下角的 + 开始一些对话。 + 您的聊天室将显示在此处。点击右下角的 + 来找到现有的聊天室或者创建你自己的聊天室。 消息已删除 显示已移除消息 对已移除消息显示占位符 @@ -1919,7 +1919,7 @@ 无法添加媒体文件到相册 无法保存媒体文件 选择新的账户密码… - 在您的其他设备上使用最新的 Element、Element Web、Element Desktop、Element iOS、Element for Android,或其他能够交叉签名的 Matrix 客户端 + 在你的其他设备上使用最新的Element 网页版、Element 桌面版、Element iOS 版、Element 安卓版,或其他能够交叉签名的 Matrix 客户端 Element Web \nElement Desktop Element iOS @@ -2152,4 +2152,21 @@ 如需扫描二维码,您须允许相机访问权限。 没有更多结果 开始畅聊 + 删除地址 \"%1$s\"? + 取消发布地址 \"%1$s\"? + 发布 + 手动发布新地址 + 其它发布的地址: + 主地址 + 这是主地址 + 发布的地址可以被任何服务器上的任何人用来加入您的聊天室。要发布一个地址,它必须先被设为一个本地地址。 + 发布的地址 + 聊天室地址 + 查看和管理此聊天室的地址,以及它在聊天室目录中的可见性。 + 聊天室地址 + 聊天室访问 + 改成谁都可以阅读历史只会应用于此聊天室未来的消息。已经存在的历史消息的可见性将不会改变。 + 发送密钥共享请求历史记录 + 取消发布 + 添加 \ No newline at end of file diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index d39254d506..f0a591b93d 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -572,8 +572,8 @@ \'%s\' 不是有效的別名格式 您沒有為此聊天室指定主要地址。 主地址警告 - 設定為主地址 - 取消設定為主地址 + 設定為主要地址 + 取消設定為主要地址 複製聊天室 ID 複製聊天室地址 此聊天室已啟用加密。 @@ -1148,9 +1148,9 @@ 歡迎回家! 來這裡看未讀訊息 對話 - 您的直接訊息對話將會在此顯示 + 您的直接訊息對話將會在此顯示。點擊右下角的 + 開始一些直接訊息。 聊天室 - 您的聊天室將會在此顯示 + 您的聊天室將會在此顯示。點擊右下角的 + 來尋找既有的或開始您自己的。 反應 同意 喜歡 @@ -2208,4 +2208,74 @@ 允許存取您聯絡人的權限。 要掃描 QR code,您必須允許存取攝影機。 開始聊天 + 變更您目前的 PIN + 變更 PIN + 無法預覽此聊天室。您想要加入嗎? + 目前無法存取此聊天室。 +\n請稍後再試,或是詢問聊天室管理員來檢查您是否可以存取。 + 無法擷取目前的聊天室目錄可見度 (%1$s)。 + 將此聊天室在 %1$s 的聊天室目錄中公開發佈? + 取消發佈此地址 + 發佈此地址 + 新增本地地址 + 此聊天室沒有本地地址 + 設定此聊天室的地址,這樣使用者就可以透過您的家伺服器 (%1$s) 尋找此聊天室 + 本地地址 + 新發佈的地址(例如:#alias:server) + 尚無其他已發佈的地址。 + 尚無其他已發佈的地址,在下面新增一個。 + 將此聊天室在 %1$s 的聊天室目錄中公開發佈? + 刪除地址「%1$s」? + 取消發佈地址「%1$s」? + 發佈 + 手動發佈新地址 + 其他已發佈地址: + 主要地址 + 這是主要地址 + 任何伺服器上的任何人都可以用已發佈的地址加入您的聊天室。要發佈地址,必須先將其設為本地地址才行。 + 已發佈的地址 + 聊天室地址 + 檢視並管理此聊天室的地址,以及其在聊天室目錄中的可見性。 + 聊天室地址 + 聊天室存取權 + 對可讀取歷史紀錄的人的變更將僅試用於此聊天室中的未來訊息。現有歷史紀錄的可見性將保持不便。 + 取消發佈 + 新增 + 傳送雪 ❄️ + 傳送五彩紙屑 🎉 + 與雪一同傳送指定的訊息 + 與五彩紙屑一同傳送指定的訊息 + 清除歷史紀錄 + 單一登入 + 使用 %s 登入 + 使用 %s 註冊 + 繼續 %s + + 使用 /confetti 指令或傳送包含 ❄️ 或 🎉 的訊息 + 顯示聊天效果 + 變更主題 + 升級聊天室 + 傳送 m.room.server_acl 活動 + 變更權限 + 變更聊天室名稱 + 變更歷史紀錄可見性 + 啟用聊天室加密 + 變更聊天室的主要位置 + 變更聊天室大頭照 + 修改小工具 + 通知每個人 + 移除其他人傳送的訊息 + 封鎖使用者 + 踢除使用者 + 變更設定 + 邀請使用者 + 傳送訊息 + 預設角色 + 您無權更新聊天室各部份所需的角色 + 選取聊天室各部份所需的角色 + 權限 + 檢視並更新聊天室各部份所需的角色。 + 聊天室權限 + 此聊天室不公開。沒有邀請,您將無法重新加入。 + 系統預設值 \ No newline at end of file diff --git a/vector/src/main/res/values/array.xml b/vector/src/main/res/values/array.xml index e56844e2e8..2c4bc135e5 100644 --- a/vector/src/main/res/values/array.xml +++ b/vector/src/main/res/values/array.xml @@ -92,12 +92,14 @@ + @string/system_theme @string/light_theme @string/dark_theme @string/black_them + system light dark black diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 61bc5dec94..fe9f0de9a1 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -8,6 +8,7 @@ Latn + System Default Light Theme Dark Theme Black Theme @@ -490,6 +491,7 @@ Leave room Are you sure you want to leave the room? + This room is not public. You will not be able to rejoin without an invite. Are you sure you want to remove %s from this chat? Create @@ -608,6 +610,33 @@ The certificate has changed from a previously trusted one to one that is not trusted. The server may have renewed its certificate. Contact the server administrator for the expected fingerprint. Only accept the certificate if the server administrator has published a fingerprint that matches the one above. + + Room permissions + View and update the roles required to change various parts of the room. + + "Permissions" + "Select the roles required to change various parts of the room" + "You don't have permission to update the roles required to change various parts of the room" + + Default role + Send messages + Invite users + Change settings + Kick users + Ban users + Remove messages sent by others + Notify everyone + Modify widgets + Change room avatar + Change main address for the room + Enable room encryption + Change history visibility + Change room name + Change permissions + Send m.room.server_acl events + Upgrade the room + Change topic + Room Details People @@ -888,6 +917,8 @@ Preview media before sending Send message with enter Enter button of the soft keyboard will send message instead of adding a line break + Show emoji keyboard + Add a button on message composer to open emoji keyboard Secure Backup Manage diff --git a/vector/src/main/res/xml/vector_settings_preferences.xml b/vector/src/main/res/xml/vector_settings_preferences.xml index 74b1f882ee..4150432149 100644 --- a/vector/src/main/res/xml/vector_settings_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_preferences.xml @@ -13,7 +13,7 @@ app:fragment="im.vector.app.features.settings.locale.LocalePickerFragment" /> + +