Merge branch 'develop' into feature/ons/fix_edit_poll

This commit is contained in:
Onuray Sahin 2023-01-11 14:05:28 +03:00
commit 49367824b0
119 changed files with 1219 additions and 280 deletions

View file

@ -11,7 +11,7 @@ jobs:
- run: |
npm install --save-dev @babel/plugin-transform-flow-strip-types
- name: Danger
uses: danger/danger-js@11.2.0
uses: danger/danger-js@11.2.1
with:
args: "--dangerfile ./tools/danger/dangerfile.js"
env:

View file

@ -66,7 +66,7 @@ jobs:
yarn add danger-plugin-lint-report --dev
- name: Danger lint
if: always()
uses: danger/danger-js@11.2.0
uses: danger/danger-js@11.2.1
with:
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
env:

View file

@ -1,3 +1,30 @@
Changes in Element v1.5.20 (2023-01-10)
=======================================
Features ✨
----------
- "[Rich text editor] Add list formatting buttons to the rich text editor" ([#7887](https://github.com/vector-im/element-android/issues/7887))
Bugfixes 🐛
----------
- ReplyTo are not updated if the original message is edited or deleted. ([#5546](https://github.com/vector-im/element-android/issues/5546))
- Observe ViewEvents only when resumed and ensure ViewEvents are not lost. ([#7724](https://github.com/vector-im/element-android/issues/7724))
- [Session manager] Missing info when a session does not support encryption ([#7853](https://github.com/vector-im/element-android/issues/7853))
- Reduce number of crypto database transactions when handling the sync response ([#7879](https://github.com/vector-im/element-android/issues/7879))
- [Voice Broadcast] Stop listening if we reach the last received chunk and there is no last sequence number ([#7899](https://github.com/vector-im/element-android/issues/7899))
- Handle network error on API `rooms/{roomId}/threads` ([#7913](https://github.com/vector-im/element-android/issues/7913))
In development 🚧
----------------
- [Poll] Render active polls list of a room
- [Poll] Render past polls list of a room ([#7864](https://github.com/vector-im/element-android/issues/7864))
Other changes
-------------
- fix: increase font size for messages ([#5717](https://github.com/vector-im/element-android/issues/5717))
- Add trim to username input on the app side and SDK side when sign-in ([#7111](https://github.com/vector-im/element-android/issues/7111))
Changes in Element v1.5.18 (2023-01-02)
=======================================

View file

@ -127,7 +127,8 @@ GEM
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
git (1.11.0)
git (1.13.0)
addressable (~> 2.8)
rchardet (~> 1.8)
google-apis-androidpublisher_v3 (0.25.0)
google-apis-core (>= 0.7, < 2.a)

View file

@ -27,9 +27,9 @@ buildscript {
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.1.1'
classpath 'com.google.gms:google-services:4.3.14'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.5.0.2730'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
classpath "com.likethesalad.android:stem-plugin:2.2.3"
classpath 'org.owasp:dependency-check-gradle:7.4.3'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
classpath "com.likethesalad.android:stem-plugin:2.3.0"
classpath 'org.owasp:dependency-check-gradle:7.4.4'
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.20"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
@ -48,7 +48,7 @@ plugins {
id "com.google.devtools.ksp" version "1.7.22-1.0.8"
// Dependency Analysis
id 'com.autonomousapps.dependency-analysis' version "1.17.0"
id 'com.autonomousapps.dependency-analysis' version "1.18.0"
// Gradle doctor
id "com.osacky.doctor" version "0.8.1"
}

View file

@ -1 +0,0 @@
ReplyTo are not updated if the original message is edited or deleted.

View file

@ -1 +0,0 @@
[Session manager] Missing info when a session does not support encryption

View file

@ -1,2 +0,0 @@
[Poll] Render active polls list of a room
[Poll] Render past polls list of a room

View file

@ -1 +0,0 @@
Reduce number of crypto database transactions when handling the sync response

View file

@ -1 +0,0 @@
"[Rich text editor] Add list formatting buttons to the rich text editor"

View file

@ -1 +0,0 @@
[Voice Broadcast] Stop listening if we reach the last received chunk and there is no last sequence number

1
changelog.d/7900.feature Normal file
View file

@ -0,0 +1 @@
Render ended polls

1
changelog.d/7930.feature Normal file
View file

@ -0,0 +1 @@
"[Rich text editor] Update list item bullet appearance"

View file

@ -18,7 +18,7 @@ def markwon = "4.6.2"
def moshi = "1.14.0"
def lifecycle = "2.5.1"
def flowBinding = "1.2.0"
def flipper = "0.176.0"
def flipper = "0.176.1"
def epoxy = "5.0.0"
def mavericks = "3.0.1"
def glide = "4.14.2"
@ -27,7 +27,7 @@ def jjwt = "0.11.5"
// Temporary version to unblock #6929. Once 0.16.0 is released we should use it, and revert
// the whole commit which set version 0.16.0-SNAPSHOT
def vanniktechEmoji = "0.16.0-SNAPSHOT"
def sentry = "6.9.2"
def sentry = "6.11.0"
def fragment = "1.5.5"
// Testing
def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
@ -60,7 +60,7 @@ ext.libs = [
'work' : "androidx.work:work-runtime-ktx:2.7.1",
'autoFill' : "androidx.autofill:autofill:1.1.0",
'preferenceKtx' : "androidx.preference:preference-ktx:1.2.0",
'junit' : "androidx.test.ext:junit:1.1.3",
'junit' : "androidx.test.ext:junit:1.1.5",
'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
@ -86,7 +86,7 @@ ext.libs = [
'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution",
'appdistribution' : "com.google.firebase:firebase-appdistribution:$appDistribution",
// Phone number https://github.com/google/libphonenumber
'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.13.3"
'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.13.4"
],
dagger : [
'dagger' : "com.google.dagger:dagger:$dagger",
@ -101,7 +101,7 @@ ext.libs = [
],
element : [
'opusencoder' : "io.element.android:opusencoder:1.1.0",
'wysiwyg' : "io.element.android:wysiwyg:0.13.0"
'wysiwyg' : "io.element.android:wysiwyg:0.15.0"
],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Vlákna jsou nyní povolena ve výchozím nastavení.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Vlákna jsou nyní povolena ve výchozím nastavení.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Threads sind nun standardmäßig aktiviert.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Die wichtigsten Änderungen in dieser Version: Threads sind nun standardmäßig aktiviert.
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Mainly bugfixing!
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -1 +1 @@
Sekura kaj sencentrigita vokado kaj babilado. Tenu viajn datumojn sekuraj.
Grupa mesaĝisto - ĉifrita mesaĝado, grupa babilejo kaj videovokoj

View file

@ -1 +1 @@
Element (antaŭe Riot.im)
Element - Sekura Tujmesaĝilo

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: jutulõngad on vaikimisi kasutusel.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: jutulõngad on vaikimisi kasutusel.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
تغییرات عمده در این نگارش: رشته‌ها اکنون به صورت پیش‌گزیده به کار افتاده‌اند.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
تغییرات عمده در این نگارش: رشته‌ها اکنون به صورت پیش‌گزیده به کار افتاده‌اند.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Fils de discussion activés par défaut.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Fils de discussion activés par défaut.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Legnagyobb változtatás ebben a verzióban: Új üzenetszálak alapból bekapcsolva!
Teljes változási napló: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Legnagyobb változtatás ebben a verzióban: Az üzenetszálak alapból bekapcsolva!
Teljes változási napló: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Utasan sekarang diaktifkan secara bawaan.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Utasan sekarang diaktifkan secara bawaan.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: i messaggi in conversazioni sono attivi in modo predefinito.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: i messaggi in conversazioni sono attivi in modo predefinito.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Vlákna sú teraz predvolene zapnuté.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Vlákna sú teraz predvolene zapnuté.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Гілки відтепер типово ввімкнено.
Перелік усіх змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Гілки відтепер типово ввімкнено.
Перелік усіх змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:討論串現在預設啟用。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:討論串現在預設啟用。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -39,7 +39,6 @@
<string name="medium_phone_number">Telefonnummer</string>
<string name="room_displayname_room_invite">Invitation til rum</string>
<string name="room_displayname_two_members">%1$s og %2$s</string>
<string name="room_displayname_empty_room">Tomt rum</string>
<string name="light_theme">Lyst Tema</string>
<string name="dark_theme">Mørkt Tema</string>
@ -82,7 +81,6 @@
<string name="matrix_only_filter">Kun Matrix kontakter</string>
<string name="no_result_placeholder">Ingen resultater</string>
<string name="rooms_header">Rum</string>
<string name="send_bug_report_include_logs">Send logfiler</string>
<string name="send_bug_report_include_crash_logs">Send crashlogfiler</string>
<string name="send_bug_report_include_screenshot">Send screenshot</string>
@ -110,10 +108,8 @@
<string name="auth_invalid_email">Dette ligner ikke en gyldig emailadresse</string>
<string name="auth_email_already_defined">Den emailadresse er allerede i brug.</string>
<string name="auth_forgot_password">Glemt adgangskode?</string>
<string name="auth_recaptcha_message">Denne Home Server vil gerne være sikker på du ikke er en robot</string>
<string name="auth_reset_password_error_unauthorized">Kunne ikke verificere emailadresse: vær sikker på du klikkede på linket i emailen</string>
<string name="login_error_invalid_home_server">Skriv gyldig URL</string>
<string name="login_error_bad_json">Fejlformet JSON</string>
<string name="login_error_not_json">Indeholdt ikke gyldig JSON</string>
@ -134,15 +130,10 @@
<string name="call_in_progress">Opkald I Gang</string>
<string name="call_error_user_not_responding">Den anden side tog den ikke.</string>
<string name="permissions_rationale_popup_title">Information</string>
<string name="permissions_rationale_msg_record_audio">${app_name} skal bruge tilladelse til at bruge din mikrofon for at lave lydopkald.</string>
<string name="permissions_rationale_msg_camera_and_audio">${app_name} skal bruge tilladelse til at bruge dit kamera og din mikrofon for at lave videoopkald.
Giv venligst tilladelse ved næste pop-up for at lave opkaldet.</string>
<string name="yes">JA</string>
<string name="no">NEJ</string>
<string name="_continue">Fortsæt</string>
@ -150,7 +141,6 @@ Giv venligst tilladelse ved næste pop-up for at lave opkaldet.</string>
<string name="action_join">Forbind</string>
<string name="action_reject">Afvis</string>
<string name="room_jump_to_first_unread">Spring til første ulæste besked.</string>
<string name="room_participants_leave_prompt_title">Forlad rum</string>
<string name="room_participants_leave_prompt_msg">Er du sikker på at du vil forlade rummet?</string>
<string name="room_participants_header_direct_chats">DIREKTE CHATS</string>
@ -163,7 +153,7 @@ Giv venligst tilladelse ved næste pop-up for at lave opkaldet.</string>
<string name="room_participants_power_level_prompt">Du vil ikke kunne omgøre denne ændring da du forfremmer brugeren til at have samme magt niveau som dig selv.
Er du sikker?</string>
<string name="room_one_user_is_typing">%s skriver…</string>
<string name="room_two_users_are_typing">"%1$s &amp; %2$s skriver…"</string>
<string name="room_two_users_are_typing">%1$s &amp; %2$s skriver…</string>
<string name="room_many_users_are_typing">%1$s, %2$s og andre skriver…</string>
<string name="room_do_not_have_permission_to_post">Du har ikke tilladelse til at skrive i dette rum</string>
<string name="ssl_trust">Stol på</string>
@ -186,7 +176,6 @@ Er du sikker?</string>
<item quantity="other">%d medlemsændringer</item>
</plurals>
<string name="list_members">Medlemsoversigt</string>
<plurals name="room_title_members">
<item quantity="one">1 medlem</item>
<item quantity="other">%d medlemmer</item>
@ -199,8 +188,6 @@ Er du sikker?</string>
<string name="search_hint">Søg</string>
<string name="search_members_hint">Filtrer medlemmer i rum</string>
<string name="search_no_results">Ingen resultater</string>
<string name="room_settings_all_messages">Alle meddelelser</string>
<string name="room_settings_add_homescreen_shortcut">Opret genvej på startskærm</string>
<string name="settings_profile_picture">Profilbillede</string>
@ -291,4 +278,4 @@ Er du sikker?</string>
<string name="notice_room_created">%1$s oprettede rummet</string>
<string name="notice_room_invite_no_invitee_by_you">Din invitation</string>
<string name="link_this_email_settings_link">Forbind denne email med din konto</string>
</resources>
</resources>

View file

@ -2889,4 +2889,13 @@
<string name="set_link_create">Link erstellen</string>
<string name="set_link_link">Link</string>
<string name="set_link_text">Text</string>
<string name="settings_access_token_summary">Dein Zugriffstoken gewährt vollen Zugriff auf dein Konto. Teile ihn mit niemandem.</string>
<string name="settings_access_token">Zugriffstoken</string>
<string name="rich_text_editor_bullet_list">Unsortierte Liste umschalten</string>
<string name="rich_text_editor_numbered_list">Nummerierte Liste umschalten</string>
<string name="room_polls_ended_no_item">In diesem Raum gibt es noch keine abgeschlossenen Umfragen</string>
<string name="room_polls_ended">Vergangene Umfragen</string>
<string name="room_polls_active_no_item">In diesem Raum gibt es keine aktiven Umfragen</string>
<string name="room_polls_active">Aktive Umfragen</string>
<string name="room_profile_section_more_polls">Umfrageverlauf</string>
</resources>

View file

@ -718,8 +718,8 @@
<string name="settings_discovery_please_enter_server">Bonvolu enigi la URL-on de identiga servilo</string>
<string name="settings_discovery_bad_identity_server">Ne povis konektiĝi al identiga servilo</string>
<string name="settings_discovery_enter_identity_server">Enigu URL-on de identiga servilo</string>
<string name="settings_discovery_confirm_mail_not_clicked">Ni sendis al vi konfirman retleteron al %s, bonvolu unue kontroli vian retpoŝton kaj klaki la konfirman ligilon</string>
<string name="settings_discovery_confirm_mail">Ni sendis al vi konfirman retleteron al %s; kontrolu vian retpoŝton kaj klaku la konfirman ligilon</string>
<string name="settings_discovery_confirm_mail_not_clicked">Ni sendis retleteron al %s, bonvolu unue kontroli vian retpoŝton kaj klaki la konfirman ligilon</string>
<string name="settings_discovery_confirm_mail">Ni sendis retleteron al %s; kontrolu vian retpoŝton kaj klaku la konfirman ligilon</string>
<string name="settings_discovery_msisdn_title">Troveblaj telefonnumeroj</string>
<string name="settings_discovery_disconnect_identity_server_info">Malkonekto de via identiga servilo signifas, ke vi ne estos trovebla de aliaj uzantoj kaj ne povos inviti aliulojn per retpoŝtadreso aŭ telefono.</string>
<string name="settings_discovery_no_msisdn">Elektebloj pri trovado aperos post aldono de telefonnumero.</string>
@ -2201,4 +2201,4 @@
<string name="call_ringing">Sonorante…</string>
<string name="spaces">Aroj</string>
<string name="initial_sync_request_reason_unignored_users">- Iom uzantoj reatentita</string>
</resources>
</resources>

View file

@ -50,7 +50,7 @@
<string name="notice_room_invite_with_reason">%1$s ha invitado a %2$s. Razón: %3$s</string>
<string name="notice_room_invite_you_with_reason">%1$s te ha invitado. Razón: %2$s</string>
<string name="notice_room_join_with_reason">%1$s se ha unido. Razón: %2$s</string>
<string name="notice_room_leave_with_reason">%1$s se ha ido. Razón: %2$s</string>
<string name="notice_room_leave_with_reason">%1$s dejó la sala. Razón: %2$s</string>
<string name="notice_room_reject_with_reason">%1$s ha rechadazo la invitación. Razón: %2$s</string>
<string name="notice_room_remove_with_reason">%1$s expulsó a %2$s. Razón: %3$s</string>
<string name="notice_room_ban_with_reason">%1$s ha baneado a %2$s. Razón: %3$s</string>
@ -81,17 +81,17 @@
<string name="notice_room_guest_access_can_join">%1$s ha permitido que los invitados se unan a la sala.</string>
<string name="notice_room_guest_access_forbidden">%1$s ha impedido que los invitados se unan a la sala.</string>
<string name="notice_end_to_end_ok">%1$s ha activado el cifrado Extremo-a-Extremo.</string>
<string name="notice_end_to_end_unknown_algorithm">%1$s ha activado el cifrado Extremo-a-Extremo (algoritmo no reconocido %2$s).</string>
<string name="notice_end_to_end_unknown_algorithm">%1$s ha activado el cifrado extremo-a-extremo (algoritmo no reconocido %2$s).</string>
<string name="notice_room_invite_no_invitee_by_you">Tu invitación</string>
<string name="notice_room_created">%1$s creó la sala</string>
<string name="notice_room_created_by_you">Creaste la sala</string>
<string name="notice_room_invite_by_you">Invitaste a %1$s</string>
<string name="notice_room_join_by_you">Te uniste a la Sala</string>
<string name="notice_room_leave_by_you">Dejaste la Sala</string>
<string name="notice_room_leave_by_you">Dejaste la sala</string>
<string name="notice_room_reject_by_you">Rechazaste la invitación</string>
<string name="notice_room_remove_by_you">Tu pateaste a %1$s</string>
<string name="notice_room_unban_by_you">Tu desbanaste a %1$s</string>
<string name="notice_room_ban_by_you">Usted prohibió a %1$s</string>
<string name="notice_room_ban_by_you">Excluiste a %1$s</string>
<string name="notice_room_withdraw_by_you">Retiró la invitación de %1$s\'s</string>
<string name="notice_avatar_url_changed_by_you">Cambiaste tu avatar</string>
<string name="notice_display_name_set_by_you">Establece su nombre de visualización en %1$s</string>
@ -152,10 +152,10 @@
<string name="notice_room_aliases_added_and_removed_by_you">Agregaste %1$s y quitaste %2$s como direcciones para esta sala.</string>
<string name="notice_room_canonical_alias_set_by_you">Estableciste la dirección principal de esta sala en %1$s.</string>
<string name="notice_room_canonical_alias_unset_by_you">Quitaste la dirección principal de esta sala.</string>
<string name="notice_room_guest_access_can_join_by_you">Ha permitido que los invitados se unan a la sala.</string>
<string name="notice_room_guest_access_forbidden_by_you">Ha impedido que los invitados se unan a la sala.</string>
<string name="notice_room_guest_access_can_join_by_you">Has permitido que los invitados se unan a la sala.</string>
<string name="notice_room_guest_access_forbidden_by_you">Has impedido que los invitados se unan a la sala.</string>
<string name="notice_end_to_end_ok_by_you">Has activado el cifrado Extremo-a-Extremo.</string>
<string name="notice_end_to_end_unknown_algorithm_by_you">Has activado el cifrado Extremo-a-Extremo (algoritmo %1$s no reconocido).</string>
<string name="notice_end_to_end_unknown_algorithm_by_you">Has activado el cifrado extremo-a-extremo (algoritmo %1$s no reconocido).</string>
<string name="notice_direct_room_guest_access_forbidden_by_you">Has impedido que invitados se unan a la sala.</string>
<string name="notice_direct_room_guest_access_can_join_by_you">Has permitido a invitados unirse aquí.</string>
<string name="notice_direct_room_leave_with_reason_by_you">Te has ido. Razón: %1$s</string>
@ -163,7 +163,7 @@
<string name="notice_direct_room_third_party_invite_by_you">Has invitado a %1$s</string>
<string name="notice_direct_room_update_by_you">Has actualizado aquí.</string>
<string name="notice_made_future_direct_room_visibility_by_you">Has hecho futuros mensajes visibles a %1$s</string>
<string name="notice_direct_room_leave_by_you">Te saliste de la sala</string>
<string name="notice_direct_room_leave_by_you">Has dejado la sala</string>
<string name="notice_direct_room_join_by_you">Te uniste</string>
<string name="notice_direct_room_created_by_you">Creaste la conversación</string>
<string name="notice_direct_room_guest_access_forbidden">%1$s ha impedido que invitados se unan a la sala.</string>
@ -255,7 +255,7 @@
<string name="bottom_action_rooms">Salas y Grupos</string>
<string name="home_filter_placeholder_home">Filtrar salas</string>
<string name="invitations_header">Invitaciones</string>
<string name="low_priority_header">Prioridad baja</string>
<string name="low_priority_header">Baja prioridad</string>
<string name="direct_chats_header">Conversaciones</string>
<string name="matrix_only_filter">Solo contactos de Matrix</string>
<string name="no_result_placeholder">No hay resultados</string>
@ -429,7 +429,7 @@
<string name="encryption_import_import">Importar</string>
<string name="encryption_never_send_to_unverified_devices_title">Cifrar solo a sesiones verificadas</string>
<string name="encryption_never_send_to_unverified_devices_summary">Nunca enviar mensajes cifrados a sesiones sin verificar desde esta sesión.</string>
<string name="encryption_information_not_verified">SIN Verificar</string>
<string name="encryption_information_not_verified">Sin Verificar</string>
<string name="encryption_information_verified">Verificado</string>
<string name="encryption_information_verify">Verificar</string>
<string name="encryption_information_verify_device_warning">Para verificar que esta sesión es confiable, por favor contacta a su dueño por algún otro medio (ej. cara a cara o por teléfono) y pregúntale si la clave que ve en sus Ajustes de Usuario para esta sesión coincide con la clave a continuación:</string>
@ -819,7 +819,7 @@
<string name="keys_backup_settings_valid_signature_from_unverified_device">La copia de seguridad tiene una firma valida de la sesión no verificada %s</string>
<string name="keys_backup_settings_invalid_signature_from_verified_device">La copia de seguridad tiene una firma inválida de la sesión verificada %s</string>
<string name="keys_backup_settings_invalid_signature_from_unverified_device">La copia de seguridad tiene una firma inválida de la sesión no verificada %s</string>
<string name="keys_backup_settings_untrusted_backup">Para usar la copia de seguridad de la clave en esta sesión introduzca su contraseña o su clave de recuperación ahora.</string>
<string name="keys_backup_settings_untrusted_backup">Para usar la copia de seguridad de la clave en esta sesión introduce tu contraseña o tu clave de recuperación ahora.</string>
<string name="keys_backup_settings_delete_confirm_message">¿Deseas borrar tus claves de cifrado guardadas en el servidor\? No podrás usar tu clave de recuperación para leer el historial de mensajes cifrados.</string>
<string name="settings_play_shutter_sound">Reproducir sonido de cámara</string>
<string name="encryption_information_unknown_ip">ip desconocida</string>
@ -1182,7 +1182,7 @@
<string name="verification_request_other_cancelled">%s cancelada</string>
<string name="verification_request_you_cancelled">Cancelado por usted</string>
<string name="verification_request_other_accepted">%s aceptada</string>
<string name="verification_request_you_accepted">Aceptado por usted</string>
<string name="verification_request_you_accepted">Aceptaste</string>
<string name="verification_sent">Verificacion enviada</string>
<string name="verification_request">Solicitud de verificación</string>
<string name="verification_verify_device">Verifica esta Sesion</string>
@ -1239,7 +1239,7 @@
<string name="verification_profile_warning">Precaucion</string>
<string name="room_member_profile_failed_to_get_devices">Error al obtener sesiones</string>
<string name="room_member_profile_sessions_section_title">Sesiones</string>
<string name="trusted">Confirmado</string>
<string name="trusted">Confiable</string>
<string name="not_trusted">No es confiable</string>
<string name="initialize_cross_signing">Inicializar Firmas Cruzadas</string>
<string name="reset_cross_signing">Restablecer claves</string>
@ -1255,7 +1255,7 @@
<string name="delete_event_dialog_reason_hint">Razón para redactar</string>
<string name="login_default_session_public_name">${app_name} Android</string>
<string name="refresh">Refrescar</string>
<string name="new_session">Nuevo inicio de sesión detectado . ¿Fue usted\?</string>
<string name="new_session">Nuevo inicio de sesión detectado . ¿Has sido tú\?</string>
<string name="verify_new_session_was_not_me">Este no era yo</string>
<string name="verify_new_session_compromized">Su cuenta puede estar comprometida</string>
<string name="verification_cancelled">Verificación cancelada</string>
@ -1263,7 +1263,7 @@
<string name="message_key">Clave de mensaje</string>
<string name="bootstrap_finish_title">¡Listo!</string>
<string name="encryption_enabled">Cifrado habilitado</string>
<string name="room_created_summary_item_by_you">Sala creada y configurada por usted.</string>
<string name="room_created_summary_item_by_you">Creaste y configuraste la sala.</string>
<string name="qr_code_scanned_verif_waiting">Esperando por %s…</string>
<string name="settings_notification_configuration">Ajuste de Notificaciones</string>
<string name="room_message_placeholder">Mensaje…</string>
@ -1279,7 +1279,7 @@
<string name="settings_security_pin_code_summary">Si decea resetear su PIN, toque Olvidé PIN para cerrar sesión y restablecer.</string>
<string name="settings_phone_numbers">Numeros telefonicos</string>
<string name="settings_emails_and_phone_numbers_title">Correos y numeros telefonicos</string>
<string name="settings_emails_and_phone_numbers_summary">Administre el correo y numero telefonico de su cuenta</string>
<string name="settings_emails_and_phone_numbers_summary">Administra las direcciones de correo y/o números telefónicos relacionados a tu cuenta de Matrix</string>
<string name="settings_show_redacted">Mostrar mensajes eliminados</string>
<string name="settings_show_redacted_summary">Indicar marca de mensaje eliminado</string>
<string name="uploads_files_title">ARCHIVOS</string>
@ -1357,7 +1357,7 @@
<string name="room_join_rules_invite_by_you">Hiciste la sala solo por invitación.</string>
<string name="login_server_matrix_org_text">Únase gratis a millones de personas en el mayor servidor público</string>
<string name="login_signin_sso">Continuar con SSO</string>
<string name="login_server_url_form_modular_hint">Dirección de servicios de Element Matrix</string>
<string name="login_server_url_form_modular_hint">Dirección de Element Matrix Services</string>
<string name="login_server_url_form_common_notice">Ingrese la dirección del servidor que desea utilizar</string>
<string name="login_reset_password_notice">Se enviará un correo electrónico de verificación a su bandeja de entrada para confirmar la configuración de su nueva contraseña.</string>
<string name="login_reset_password_submit">Siguiente</string>
@ -1407,7 +1407,7 @@
<string name="login_signup_cancel_confirmation_title">Advertencia</string>
<string name="login_signup_cancel_confirmation_content">Tu cuenta aún no está creada. ¿Detener el proceso de registro\?</string>
<string name="login_a11y_choose_matrix_org">Seleccione matrix.org</string>
<string name="login_a11y_choose_modular">Seleccionar servicios de matriz de elementos</string>
<string name="login_a11y_choose_modular">Seleccionar Element Matrix Services</string>
<string name="login_a11y_choose_other">Seleccione un servidor doméstico personalizado</string>
<string name="login_a11y_captcha_container">Realiza el desafío de captcha</string>
<string name="login_terms_title">Acepta los términos para continuar</string>
@ -1453,7 +1453,7 @@
\nVuelva a iniciar sesión para acceder a los datos y mensajes de su cuenta.</string>
<string name="soft_logout_clear_data_dialog_e2e_warning_content">Perderás el acceso a los mensajes seguros a menos que inicies sesión para recuperar tus claves de cifrado.</string>
<string name="soft_logout_sso_not_same_user_error">La sesión actual es para el usuario %1$s y usted proporciona las credenciales para el usuario %2$s. Esto no está suportado por ${app_name}.
\nPrimero borre los datos, luego inicie sesión nuevamente con otra cuenta.</string>
\nPrimero borra los datos, luego inicia sesión nuevamente con otra cuenta.</string>
<string name="permalink_malformed">Su enlace matrix.to estaba mal formado</string>
<string name="settings_developer_mode_summary">El modo desarrollador activa funciones ocultas y también puede hacer que la aplicación sea menos estable. ¡Solo para desarrolladores!</string>
<string name="verification_conclusion_compromised">Uno de los siguientes puede verse comprometido:
@ -1462,9 +1462,9 @@
\n- El servidor privado al que está conectado el usuario que estás verificando
\n- Su conexión a internet o la de otros usuarios
\n- Su dispositivo o el de otros usuarios</string>
<string name="room_profile_encrypted_subtitle">Los mensajes de esta sala están cifrados Extremo-a-Extremo.
<string name="room_profile_encrypted_subtitle">Los mensajes de esta sala están cifrados de extremo-a-extremo.
\n
\nSus mensajes están protegidos y sólo usted y el destinatario tienen las claves únicas para descifrarlos.</string>
\nTus mensajes están protegidos y sólo tu y el destinatario tienen las claves únicas para descifrarlos.</string>
<string name="verify_cannot_cross_sign">Esta sesión no puede compartir esta verificación con sus otras sesiones.
\nLa verificación se guardará localmente y se compartirá en una versión futura de la aplicación.</string>
<string name="command_description_rainbow_emote">Envía el emote dado coloreado como un arcoíris</string>
@ -1474,7 +1474,7 @@
<string name="verification_emoji_notice">Verifica si los mismos emojis aparecen en el mismo orden en ambos usuarios.</string>
<string name="verification_code_notice">Compare el código con el que se muestra en la pantalla del otro usuario.</string>
<string name="verification_conclusion_ok_notice">Los mensajes con este usuario están cifrados Extremo-a-Extremo y no pueden ser leídos por terceros.</string>
<string name="verification_conclusion_ok_self_notice">Su nueva sesión ahora está verificada. Tiene acceso a sus mensajes cifrados y otros usuarios lo verán como de confianza.</string>
<string name="verification_conclusion_ok_self_notice">Tu nueva sesión acaba de verificarse y ahora tiene acceso a tus mensajes cifrados y otros usuarios la verán como de confianza.</string>
<string name="encryption_information_dg_xsigning_complete">La firma cruzada está habilitada
\n Claves privadas en el dispositivo.</string>
<string name="encryption_information_dg_xsigning_trusted">La firma cruzada está habilitada
@ -1484,8 +1484,8 @@
\nLas claves no son de confianza</string>
<string name="settings_hs_admin_e2e_disabled">El administrador de su servidor ha desactivado el cifrado Extremo-a-Extremo de forma predeterminada en salas privadas y mensajes directos.</string>
<string name="settings_failed_to_get_crypto_device_info">No hay información criptográfica disponible</string>
<string name="settings_active_sessions_verified_device_desc">Esta sesión es confiable para mensajería segura porque usted la verificó:</string>
<string name="settings_active_sessions_unverified_device_desc">Verifique esta sesión para marcarla como confiable y otorgarle acceso a mensajes cifrados. Si no inició sesión en esta sesión, su cuenta puede verse comprometida:</string>
<string name="settings_active_sessions_verified_device_desc">Esta sesión es confiable para mensajería segura porque la verificaste:</string>
<string name="settings_active_sessions_unverified_device_desc">Verifica esta sesión para marcarla como confiable y otorgarle acceso a mensajes cifrados. Si no iniciaste sesión en esta sesión, su cuenta puede haber sido comprometida:</string>
<plurals name="settings_active_sessions_count">
<item quantity="one">%d sesión activa</item>
<item quantity="other">%d sesiones activas</item>
@ -1510,8 +1510,8 @@
<string name="settings_key_requests">Solicitudes clave</string>
<string name="e2e_use_keybackup">Desbloquear el historial de mensajes cifrados</string>
<string name="verify_new_session_notice">Utilice esta sesión para verificar su nuevo, otorgándole acceso a mensajes cifrados.</string>
<string name="verify_cancel_self_verification_from_untrusted">Si cancela, no podrá leer mensajes cifrados en este dispositivo y otros usuarios no confiarán en él</string>
<string name="verify_cancel_self_verification_from_trusted">Si cancela, no podrá leer mensajes cifrados en su nuevo dispositivo y otros usuarios no confiarán en él</string>
<string name="verify_cancel_self_verification_from_untrusted">Si cancelas, no podrás leer mensajes cifrados en este dispositivo y otros usuarios no confiarán en este</string>
<string name="verify_cancel_self_verification_from_trusted">Si cancelas, no podrás leer mensajes cifrados en tu nuevo dispositivo y otros usuarios no confiarán en este</string>
<string name="verify_cancel_other">No verificarás %1$s (%2$s) si cancelas ahora. Comience de nuevo en su perfil de usuario.</string>
<string name="verify_not_me_self_verification">Uno de los siguientes puede verse comprometido:
\n
@ -1524,7 +1524,7 @@
<string name="verify_cancelled_notice">Se canceló la verificación. Puede iniciar la verificación de nuevo.</string>
<string name="enter_account_password">Ingrese su %s para continuar.</string>
<string name="bootstrap_dont_reuse_pwd">No use la contraseña de su cuenta.</string>
<string name="bootstrap_info_text_2">Ingrese una frase de seguridad que solo usted conozca, que se usa para proteger secretos en su servidor.</string>
<string name="bootstrap_info_text_2">Ingresa una frase de seguridad que solo tú conozcas, que se usa para proteger secretos en tu servidor.</string>
<string name="bootstrap_loading_text">Esto puede tardar varios segundos, tenga paciencia.</string>
<string name="bootstrap_loading_title">Configurando la recuperación.</string>
<string name="keep_it_safe">Manténlo seguro</string>
@ -1561,7 +1561,7 @@
<string name="auth_invalid_login_param_space_in_password">Nombre de usuario y / o contraseña incorrectos. La contraseña ingresada comienza o termina con espacios, verifíquela.</string>
<string name="auth_invalid_login_deactivated_account">Esta cuenta ha sido desactivada.</string>
<string name="upgrade_security">Mejora de cifrado disponible</string>
<string name="security_prompt_text">Verifíquese a usted mismo y a los demás para mantener sus chats seguros</string>
<string name="security_prompt_text">Verifícate a ti mismo y a los demás para mantener tus chats seguros</string>
<string name="bootstrap_invalid_recovery_key">No es una clave de recuperación válida</string>
<string name="recovery_key_empty_error_message">Por favor introduce una clave de recuperación</string>
<string name="bootstrap_progress_checking_backup">Comprobando la clave de respaldo</string>
@ -1622,11 +1622,11 @@
<string name="bottom_sheet_setup_secure_backup_security_key_title">Usa una llave de seguridad</string>
<string name="bottom_sheet_setup_secure_backup_security_key_subtitle">Genere una clave de seguridad para almacenar en un lugar seguro, como un administrador de contraseñas o una caja fuerte.</string>
<string name="bottom_sheet_setup_secure_backup_security_phrase_title">Utilice una frase de seguridad</string>
<string name="bottom_sheet_setup_secure_backup_security_phrase_subtitle">Ingrese una frase secreta que solo usted conozca y genere una clave de respaldo.</string>
<string name="bottom_sheet_setup_secure_backup_security_phrase_subtitle">Ingresa una frase secreta que solo tú conozcas y genera una clave para tu copia de respaldo.</string>
<string name="bottom_sheet_save_your_recovery_key_title">Guarde su llave de seguridad</string>
<string name="bottom_sheet_save_your_recovery_key_content">Guarde su llave de seguridad en un lugar seguro, como un administrador de contraseñas o una caja fuerte.</string>
<string name="set_a_security_phrase_title">Establecer una frase de seguridad</string>
<string name="set_a_security_phrase_notice">Ingrese una frase de seguridad que solo usted conozca, que se usa para proteger secretos en su servidor.</string>
<string name="set_a_security_phrase_notice">Ingresa una frase de seguridad que sólo tú conozcas, que se usa para proteger secretos en tu servidor.</string>
<string name="set_a_security_phrase_hint">Frase de seguridad</string>
<string name="set_a_security_phrase_again_notice">Ingrese su Frase de seguridad nuevamente para confirmarla.</string>
<string name="room_settings_name_hint">Nombre de la Sala</string>
@ -1636,7 +1636,7 @@
<string name="notice_crypto_unable_to_decrypt_friendly">Esperando este mensaje, esto puede tardar un poco</string>
<string name="notice_crypto_unable_to_decrypt_friendly_desc">Debido al cifrado Extremo-a-Extremo, es posible que deba esperar a que llegue el mensaje de alguien porque las claves de cifrado no se le enviaron correctamente.</string>
<string name="crypto_error_withheld_blacklisted">No puede acceder a este mensaje porque ha sido bloqueado por el remitente</string>
<string name="crypto_error_withheld_unverified">No puede acceder a este mensaje porque el remitente no confía en su sesión</string>
<string name="crypto_error_withheld_unverified">No puedes acceder a este mensaje porque el remitente no confía en tu sesión</string>
<string name="crypto_error_withheld_generic">No puede acceder a este mensaje porque el remitente no envió las claves a propósito</string>
<string name="notice_crypto_unable_to_decrypt_merged">Esperando al historial de cifrado</string>
<string name="disclaimer_content">¡Nos complace anunciar que hemos cambiado de nombre! Tu aplicación está actualizada y accediste a tu cuenta.</string>
@ -1711,7 +1711,7 @@
<item quantity="one">Mostrar el dispositivo con el que puede verificar ahora</item>
<item quantity="other">Mostrar %d dispositivos con los que puede verificar ahora</item>
</plurals>
<string name="secure_backup_reset_no_history">Reiniciará sin historia, mensajes, dispositivos o usuarios verificados</string>
<string name="secure_backup_reset_no_history">Reiniciarás sin historial, ni mensajes, ni dispositivos o usuarios verificados</string>
<string name="secure_backup_reset_if_you_reset_all">Si resetea todo</string>
<string name="secure_backup_reset_all_no_other_devices">Solo haga esto si no tiene otro dispositivo con el que verificar éste.</string>
<string name="secure_backup_reset_all">Resetear todo</string>
@ -1748,7 +1748,7 @@
<string name="re_authentication_activity_title">Se necesita una nueva autenticación</string>
<string name="qr_code_not_scanned">¡Código QR no escaneado!</string>
<string name="invalid_qr_code_uri">Código QR no válido (URL no válida)!</string>
<string name="cannot_dm_self">No puede DM usted mismo!</string>
<string name="cannot_dm_self">No puedes MD a ti mismo!</string>
<string name="share_by_text">Compartir por texto</string>
<string name="settings_security_pin_code_change_pin_title">Cambiar PIN</string>
<string name="settings_security_pin_code_change_pin_summary">Cambie su PIN actual</string>
@ -1960,7 +1960,7 @@
<string name="room_settings_room_access_title">Acceso a la sala</string>
<string name="option_always_ask">Siempre preguntar</string>
<string name="spaces_header">Espacios</string>
<string name="settings_room_directory_show_all_rooms_summary">mostrar todas las salas en el directorio de salas, incluyendo salas con contenido explícito.</string>
<string name="settings_room_directory_show_all_rooms_summary">Mostrar todas las salas en el directorio de salas, incluyendo salas con contenido explícito.</string>
<string name="settings_room_directory_show_all_rooms">Mostrar salas con contenido explícito</string>
<string name="settings_category_room_directory">Directorio de la sala</string>
<string name="suggested_header">Salas sugeridas</string>
@ -2181,7 +2181,7 @@
<string name="settings_notification_new_keyword">Agregar nuevas palabra clave</string>
<string name="settings_notification_your_keywords">Tus palabras clave</string>
<string name="settings_notification_emails_enable_for_email">Habilitar notificación por correo electrónico para %s</string>
<string name="settings_notification_emails_no_emails">Para recibir un correo electrónico con una notificación, asocie un correo electrónico a su cuenta de matrix</string>
<string name="settings_notification_emails_no_emails">Para recibir notificaciones por correo electrónico, asocia una direccion de correo electrónico a tu cuenta de Matrix</string>
<string name="settings_notification_emails_category">Notificación de correo electrónico</string>
<string name="room_settings_none">Ninguno</string>
<string name="room_settings_mention_and_keyword_only">Solo menciones y palabras clave</string>
@ -2219,7 +2219,7 @@
<string name="error_voice_message_unable_to_record">No se puede grabar un mensaje de voz</string>
<string name="error_voice_message_unable_to_play">No se puede reproducir este mensaje de voz</string>
<string name="voice_message_tap_to_stop_toast">Toca tu grabación para detenerla o escucharla</string>
<string name="voice_message_n_seconds_warning_toast">%1$ds dejado</string>
<string name="voice_message_n_seconds_warning_toast">Restan %1$ds</string>
<string name="voice_message_release_to_send_toast">Mantenga presionado para grabar, suelte para enviar</string>
<string name="a11y_delete_recorded_voice_message">Eliminar grabación</string>
<string name="a11y_recording_voice_message">Grabación de mensaje de voz</string>
@ -2238,7 +2238,7 @@
<string name="shortcut_disabled_reason_sign_out">¡Se ha cerrado la sesión!</string>
<string name="shortcut_disabled_reason_room_left">¡Se ha abandonado la sala!</string>
<string name="thread_list_empty_notice">Consejo: Pulse prolongadamente un mensaje y use \"%s\" .</string>
<string name="thread_list_empty_title">Mantén las conversaciones organizadas con hilos</string>
<string name="thread_list_empty_title">Mantén las conversaciones organizadas usando hilos</string>
<string name="thread_list_modal_my_threads_subtitle">Muestra todos los hilos en que has participado</string>
<string name="thread_list_modal_my_threads_title">Mis Hilos</string>
<string name="thread_list_modal_all_threads_subtitle">Muestra todos los hilos de la sala actual</string>
@ -2457,7 +2457,7 @@
<string name="beta">BETA</string>
<string name="send_feedback_threads_title">Comentarios de la beta de hilos</string>
<string name="threads_labs_enable_notice_title">Beta de hilos</string>
<string name="initial_sync_request_reason_unignored_users">- Algunos usuarios han sido dejados de ignorar</string>
<string name="initial_sync_request_reason_unignored_users">- Algunos usuarios han dejado de ser ignorados</string>
<string name="screen_sharing_notification_description">La compartición de pantalla está en progreso</string>
<string name="screen_sharing_notification_title">${app_name} Compartición de pantalla</string>
<string name="call_stop_screen_sharing">Dejar de compartir pantalla</string>
@ -2474,7 +2474,7 @@
<string name="live_location_bottom_sheet_last_updated_at">Actualizado hace %1$s</string>
<string name="labs_enable_live_location_summary">Implementación temporal: las ubicaciones persisten en el historial de la sala</string>
<string name="labs_enable_live_location">Activar compartir ubicación en tiempo real</string>
<string name="location_share_live_remaining_time">Queda %1$s</string>
<string name="location_share_live_remaining_time">Restan %1$s</string>
<string name="location_share_live_until">Compartiendo hasta %1$s</string>
<string name="location_share_live_view">Ver ubicación en tiempo real</string>
<string name="location_share_live_ended">La ubicación en tiempo real ha terminado</string>
@ -2625,8 +2625,8 @@
\nPor favor, inténtelo de nuevo.%s</string>
<string name="font_size_use_system">Usar ajustes por defecto del sistema</string>
<string name="font_size_section_manually">Escoger manualmente</string>
<string name="font_size_section_auto">Tamaño automático de fuente</string>
<string name="font_size_title">Escoger tamaño de la fuente</string>
<string name="font_size_section_auto">Tamaño automático</string>
<string name="font_size_title">Escoge tamaño del tipo de letra</string>
<plurals name="search_space_multiple_parents">
<item quantity="one">%1$s y %2$d otro</item>
<item quantity="other">%1$s y %2$d otros</item>
@ -2659,18 +2659,33 @@
<string name="grant_permission">Otorgar permiso</string>
<string name="settings_troubleshoot_test_system_settings_permission_failed">${app_name} necesita permiso para mostrar notificaciones.
\nPor favor, otórgalo.</string>
<string name="permissions_rationale_msg_notification">${app_name} necesita permisos para mostrar notificaciones. Las notificaciones pueden mostrar tus mensajes, invitaciones, etc.
<string name="permissions_rationale_msg_notification">${app_name} necesita permiso para mostrar notificaciones. Las notificaciones pueden mostrar tus mensajes, invitaciones, etc.
\n
\nPor favor, permite el acceso en las siguientes ventanas emergentes para poder visualizar notificaciones.</string>
<string name="labs_enable_rich_text_editor_summary">Prueba el editor de texto enriquecido (pronto llegará la opción de texto sin formato plain text)</string>
\nPor favor, a continuacion, en las ventanas emergentes, permite el acceso para poder visualizar notificaciones.</string>
<string name="labs_enable_rich_text_editor_summary">Prueba el editor de texto enriquecido (pronto llegará la opción de texto simple, sin formato)</string>
<string name="labs_enable_rich_text_editor_title">Habilitar editor de texto enriquecido (rich text)</string>
<string name="labs_enable_deferred_dm_summary">Crear MD únicamente al primer mensaje</string>
<string name="labs_enable_new_app_layout_summary">Una versión simplificada de Element con pestañas opcionales</string>
<string name="labs_enable_new_app_layout_title">Habilitar nueva disposición</string>
<string name="action_stop">Sí, Parar</string>
<string name="action_stop">Sí, Detener</string>
<string name="action_deselect_all">Deseleccionar todo</string>
<string name="a11y_collapse_space_children">Ocultar los hijos de %s</string>
<string name="a11y_expand_space_children">Mostrar los hijos de %s</string>
<string name="a11y_collapse_space_children">Ocultar los subespacios de %s</string>
<string name="a11y_expand_space_children">Mostrar los subespacios de %s</string>
<string name="notice_voice_broadcast_ended_by_you">Has finalizado una transmisión de voz.</string>
<string name="notice_voice_broadcast_ended">%1$s ha finalizado una transmisión de voz.</string>
<string name="ftue_auth_choose_server_ems_subtitle">Element Matrix Services (EMS) es un servicio de alojamiento para tus comunicaciones en tiempo real. Robusto, confiable, rápido y seguro. Para saber cómo, ve a &lt;a href=\"${ftue_ems_url}\"&gt;element.io/ems&lt;/a&gt;</string>
<string name="attachment_type_voice_broadcast">Difusión de voz</string>
<string name="push_gateway_item_enabled">Habilitado:</string>
<string name="push_gateway_item_device_id">ID de sesión:</string>
<string name="error_check_network" tools:ignore="UnusedResources">Algo falló. Por favor, comprueba tu conexión de red e inténtalo nuevamente.</string>
<string name="quoting">Citando</string>
<string name="replying_to">Respondiendo a %s</string>
<string name="editing">Editando</string>
<string name="command_description_devtools">Abrir pantalla de herramientas de desarrollador</string>
<string name="room_settings_global_block_unverified_info_text">🔒 Tienes habilitado el cifrado a sesiones verificadas sólo para todas las salas en Ajustes de Seguridad.</string>
<string name="some_devices_will_not_be_able_to_decrypt">⚠ Hay dispositivos sin verificar en esta sala, los cuales no seran capaces de descifrar los mensajes que envías.</string>
<string name="labs_enable_deferred_dm_title">Habilita MDs pospuestos</string>
<string name="settings_enable_direct_share_summary">Mostrar chats recientes en el menú de compartir sistema</string>
<string name="encryption_never_send_to_unverified_devices_in_room">No enviar nunca mensajes cifrados a sesiones sin verificar en esta sala.</string>
<string name="voice_broadcast_recording_time_left">Restan %1$s</string>
</resources>

View file

@ -2881,4 +2881,13 @@
<string name="set_link_link">Link</string>
<string name="set_link_create">Loo link</string>
<string name="set_link_edit">Muuda linki</string>
<string name="room_profile_section_more_polls">Küsitluste ajalugu</string>
<string name="room_polls_active">Käimasolevad küsitlused</string>
<string name="room_polls_active_no_item">Selles jututoas pole käimasolevaid küsitlusi</string>
<string name="room_polls_ended">Varasemad küsitlused</string>
<string name="room_polls_ended_no_item">Selles jututoas pole varasemaid küsitlusi</string>
<string name="rich_text_editor_numbered_list">Lülita nummerdatud loend sisse/välja</string>
<string name="rich_text_editor_bullet_list">Lülita täpploend sisse/välja</string>
<string name="settings_access_token">Pääsuluba</string>
<string name="settings_access_token_summary">Sinu pääsuluba annab täismahulise ligipääsu sinu kasutajakontole. Palun ära jaga seda teistega.</string>
</resources>

View file

@ -2890,4 +2890,13 @@
<string name="set_link_link">پیوند</string>
<string name="set_link_text">متن</string>
<string name="rich_text_editor_link">تنظیم پیوند</string>
<string name="settings_access_token_summary">ژتون دسترسیتان، دسترسی کامل به حسابتان را می‌دهد. با هیچ‌کس هم‌رسانیش نکنید.</string>
<string name="settings_access_token">ژتون دسترسی</string>
<string name="rich_text_editor_bullet_list">تغییر وضعیت سیاههٔ گلوله‌ای</string>
<string name="rich_text_editor_numbered_list">تغییر وضعیت سیاههٔ شماره‌دار</string>
<string name="room_polls_ended_no_item">هیچ‌ نظرسنجی قدیمی‌ای در این اتاق وجود ندارد</string>
<string name="room_polls_ended">نظرسنجی‌های گذشته</string>
<string name="room_polls_active_no_item">هیچ نظرسنجی فعّالی در این اتاق وجود ندارد</string>
<string name="room_polls_active">نظرسنجی‌های فعّال</string>
<string name="room_profile_section_more_polls">تاریخچهٔ نظرسنجی‌ها</string>
</resources>

View file

@ -2890,4 +2890,13 @@
<string name="set_link_link">Lien</string>
<string name="set_link_text">Texte</string>
<string name="rich_text_editor_link">Définir un lien</string>
<string name="settings_access_token_summary">Votre jeton daccès donne un accès intégral à votre compte. Ne le partagez avec personne.</string>
<string name="settings_access_token">Jeton daccès</string>
<string name="rich_text_editor_bullet_list">(Dés)activer la liste à puce</string>
<string name="rich_text_editor_numbered_list">(Dés)activer la liste numérotée</string>
<string name="room_polls_ended_no_item">Il ny a aucun ancien sondage dans ce salon</string>
<string name="room_polls_ended">Anciens sondages</string>
<string name="room_polls_active_no_item">Il ny a aucun sondage en cours dans ce salon</string>
<string name="room_polls_active">Sondages actifs</string>
<string name="room_profile_section_more_polls">Historique des sondages</string>
</resources>

View file

@ -2836,4 +2836,13 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.</string>
<string name="set_link_link">Tautan</string>
<string name="set_link_text">Teks</string>
<string name="rich_text_editor_link">Atur tautan</string>
<string name="settings_access_token_summary">Token akses Anda memberikan akses penuh ke akun Anda. Jangan bagikan dengan siapa pun.</string>
<string name="settings_access_token">Token Akses</string>
<string name="rich_text_editor_bullet_list">Saklar daftar bulat</string>
<string name="rich_text_editor_numbered_list">Saklar daftar bernomor</string>
<string name="room_polls_ended_no_item">Tidak ada pemungutan suara sebelumnya di ruangan ini</string>
<string name="room_polls_ended">Pemungutan suara sebelumnya</string>
<string name="room_polls_active_no_item">Tidak ada pemungutan suara yang aktif di ruangan ini</string>
<string name="room_polls_active">Pemungutan suara aktif</string>
<string name="room_profile_section_more_polls">Riwayat pemungutan suara</string>
</resources>

View file

@ -2881,4 +2881,13 @@
<string name="set_link_link">Collegamento</string>
<string name="set_link_text">Testo</string>
<string name="rich_text_editor_link">Imposta collegamento</string>
<string name="settings_access_token_summary">Il tuo token di accesso ti dà l\'accesso al tuo account. Non condividerlo con nessuno.</string>
<string name="settings_access_token">Token di accesso</string>
<string name="rich_text_editor_numbered_list">Attiva/disattiva elenco numerato</string>
<string name="rich_text_editor_bullet_list">Attiva/disattiva elenco puntato</string>
<string name="room_polls_ended_no_item">In questa stanza non ci sono sondaggi passati</string>
<string name="room_polls_ended">Sondaggi passati</string>
<string name="room_polls_active_no_item">In questa stanza non ci sono sondaggi attivi</string>
<string name="room_polls_active">Sondaggi attivi</string>
<string name="room_profile_section_more_polls">Cronologia sondaggi</string>
</resources>

View file

@ -5,24 +5,24 @@
<string name="notice_room_invite_you">%1$s convidou você</string>
<string name="notice_room_join">%1$s entrou na sala</string>
<string name="notice_room_leave">%1$s saiu da sala</string>
<string name="notice_room_reject">%1$s rejeitou o convite</string>
<string name="notice_room_reject">%1$s recusou o convite</string>
<string name="notice_room_remove">%1$s removeu %2$s</string>
<string name="notice_room_unban">%1$s desbaniu %2$s</string>
<string name="notice_room_ban">%1$s baniu %2$s</string>
<string name="notice_room_withdraw">%1$s retirou o convite de %2$s</string>
<string name="notice_avatar_url_changed">%1$s mudou o avatar dela(e)</string>
<string name="notice_display_name_set">%1$s definiu o nome de exibição dela(e) para %2$s</string>
<string name="notice_display_name_changed_from">%1$s mudou o nome de exibição dela(e) de %2$s para %3$s</string>
<string name="notice_display_name_removed">%1$s removeu o nome de exibição dela(e) (era %2$s)</string>
<string name="notice_room_withdraw">%1$s desfez o convite para %2$s</string>
<string name="notice_avatar_url_changed">%1$s mudou seu avatar</string>
<string name="notice_display_name_set">%1$s definiu seu nome de exibição para %2$s</string>
<string name="notice_display_name_changed_from">%1$s mudou seu nome de exibição de %2$s para %3$s</string>
<string name="notice_display_name_removed">%1$s removeu seu nome de exibição (era %2$s)</string>
<string name="notice_room_topic_changed">%1$s mudou o tópico para: %2$s</string>
<string name="notice_room_name_changed">%1$s mudou o nome da sala para: %2$s</string>
<string name="notice_placed_video_call">%s começou uma chamada de vídeo.</string>
<string name="notice_placed_voice_call">%s começou uma chamada de voz.</string>
<string name="notice_answered_call">%s atendeu a chamada.</string>
<string name="notice_ended_call">%s terminou a chamada.</string>
<string name="notice_made_future_room_visibility">%1$s fez histórico futuro da sala visível para %2$s</string>
<string name="notice_room_visibility_invited">todos os membros da sala, do ponto que foram convidados.</string>
<string name="notice_room_visibility_joined">todos os membros da sala, do ponto que se juntaram.</string>
<string name="notice_ended_call">%s encerrou a chamada.</string>
<string name="notice_made_future_room_visibility">%1$s tornou o histórico futuro da sala visível para %2$s</string>
<string name="notice_room_visibility_invited">todos os membros da sala, a partir do ponto que foram convidados.</string>
<string name="notice_room_visibility_joined">todos os membros da sala, a partir do ponto que entraram.</string>
<string name="notice_room_visibility_shared">todos os membros da sala.</string>
<string name="notice_room_visibility_world_readable">qualquer pessoa.</string>
<string name="notice_avatar_changed_too">(avatar mudou também)</string>
@ -45,11 +45,11 @@
<string name="notice_room_invite_by_you">Você convidou %1$s</string>
<string name="notice_room_join_by_you">Você entrou na sala</string>
<string name="notice_room_leave_by_you">Você saiu da sala</string>
<string name="notice_room_reject_by_you">Você rejeitou o convite</string>
<string name="notice_room_reject_by_you">Você recusou o convite</string>
<string name="notice_room_remove_by_you">Você removeu %1$s</string>
<string name="notice_room_unban_by_you">Você desbaniu %1$s</string>
<string name="notice_room_ban_by_you">Você baniu %1$s</string>
<string name="notice_room_withdraw_by_you">Você retirou o convite de %1$s</string>
<string name="notice_room_withdraw_by_you">Você desfez o convite para %1$s</string>
<string name="notice_avatar_url_changed_by_you">Você mudou seu avatar</string>
<string name="notice_display_name_set_by_you">Você definiu seu nome de exibição para %1$s</string>
<string name="notice_display_name_changed_from_by_you">Você mudou seu nome de exibição de %1$s para %2$s</string>
@ -63,8 +63,8 @@
<string name="notice_call_candidates">%s enviou dados para configurar a chamada.</string>
<string name="notice_call_candidates_by_you">Você enviou dados para configurar a chamada.</string>
<string name="notice_answered_call_by_you">Você atendeu a chamada.</string>
<string name="notice_ended_call_by_you">Você terminou a chamada.</string>
<string name="notice_made_future_room_visibility_by_you">Você fez histórico futuro da sala visível para %1$s</string>
<string name="notice_ended_call_by_you">Você encerrou a chamada.</string>
<string name="notice_made_future_room_visibility_by_you">Você tornou o histórico futuro da sala visível para %1$s</string>
<string name="notice_room_update">%s fez o upgrade desta sala.</string>
<string name="notice_room_update_by_you">Você fez o upgrade desta sala.</string>
<string name="notice_room_name_removed_by_you">Você removeu o nome da sala</string>
@ -170,8 +170,8 @@
<string name="notice_direct_room_third_party_invite">%1$s convidou %2$s</string>
<string name="notice_direct_room_update_by_you">Você fez o upgrade aqui.</string>
<string name="notice_direct_room_update">%s fez o upgrade aqui.</string>
<string name="notice_made_future_direct_room_visibility_by_you">Você fez mensagens futuras visíveis para %1$s</string>
<string name="notice_made_future_direct_room_visibility">%1$s fez mensagens futuras visíveis para %2$s</string>
<string name="notice_made_future_direct_room_visibility_by_you">Você tornou as mensagens futuras visíveis para %1$s</string>
<string name="notice_made_future_direct_room_visibility">%1$s tornou as mensagens futuras visíveis para %2$s</string>
<string name="notice_direct_room_leave_by_you">Você saiu da sala</string>
<string name="notice_direct_room_leave">%1$s saiu da sala</string>
<string name="notice_direct_room_join_by_you">Você entrou</string>
@ -408,7 +408,7 @@
<string name="room_settings_read_history_entry_anyone">Qualquer pessoa</string>
<string name="room_settings_read_history_entry_members_only_option_time_shared">Membros somente (desde o ponto no tempo de seleção desta opção)</string>
<string name="room_settings_read_history_entry_members_only_invited">Membros somente (desde que eles foram convidados)</string>
<string name="room_settings_read_history_entry_members_only_joined">Membros somente (desde que eles se juntaram)</string>
<string name="room_settings_read_history_entry_members_only_joined">Membros somente (desde que eles entraram)</string>
<string name="room_settings_banned_users_title">Usuárias(os) banidas(os)</string>
<string name="room_settings_category_advanced_title">Avançadas</string>
<string name="room_settings_room_internal_id">ID interno desta sala</string>
@ -2009,8 +2009,8 @@
<string name="space_add_child_title">Adicionar salas</string>
<string name="space_explore_activity_title">Explorar salas</string>
<plurals name="space_people_you_know">
<item quantity="one">%d pessoa que você conhece já tem se juntado</item>
<item quantity="other">%d pessoas que você conhece já têm se juntado</item>
<item quantity="one">%d pessoa que você conhece já entrou</item>
<item quantity="other">%d pessoas que você conhece já entraram</item>
</plurals>
<string name="join_space">Juntar-Se a Espaço</string>
<string name="create_space">Criar espaço</string>
@ -2833,8 +2833,8 @@
<string name="action_deselect_all">Desselecionar todas(os)</string>
<string name="action_select_all">Selecionar todas(os)</string>
<plurals name="x_selected">
<item quantity="one">%1$d selecionada(o)</item>
<item quantity="other">%1$d selecionadas(os)</item>
<item quantity="one">%1$d selecionado(a)</item>
<item quantity="other">%1$d selecionados(as)</item>
</plurals>
<string name="error_voice_broadcast_blocked_by_someone_else_message">Alguma outra pessoa já está gravando um broadcast de voz. Espere que o broadcast de voz dela termine para começar um novo.</string>
<string name="rich_text_editor_full_screen_toggle">Alternar modo de tela cheia</string>

View file

@ -2946,4 +2946,13 @@
<string name="set_link_link">Odkaz</string>
<string name="set_link_text">Text</string>
<string name="rich_text_editor_link">Nastaviť odkaz</string>
<string name="settings_access_token_summary">Váš prístupový token poskytuje úplný prístup k vášmu účtu. S nikým ho nezdieľajte.</string>
<string name="settings_access_token">Prístupový token</string>
<string name="rich_text_editor_numbered_list">Prepnúť na číslovaný zoznam</string>
<string name="rich_text_editor_bullet_list">Prepnúť zoznam s odrážkami</string>
<string name="room_polls_ended_no_item">V tejto miestnosti nie sú žiadne predchádzajúce ankety</string>
<string name="room_polls_ended">Predchádzajúce ankety</string>
<string name="room_polls_active_no_item">V tejto miestnosti nie sú žiadne aktívne ankety</string>
<string name="room_polls_active">Aktívne ankety</string>
<string name="room_profile_section_more_polls">História ankety</string>
</resources>

View file

@ -2874,4 +2874,12 @@
<string name="set_link_create">Krijoni një lidhje</string>
<string name="set_link_link">Lidhje</string>
<string name="set_link_text">Tekst</string>
<string name="settings_access_token_summary">Tokeni juaj i hyrjeve jep hyrje të plotë në llogarinë tuaj. Mos ia jepni kujt.</string>
<string name="settings_access_token">Token Hyrjesh</string>
<string name="room_polls_ended_no_item">Ska pyetësorë të kaluar në këtë dhomë</string>
<string name="room_polls_ended">Pyetësorë të kaluar</string>
<string name="room_polls_active_no_item">Ska pyetësorë aktivë në këtë dhomë</string>
<string name="room_polls_active">Pyetësorë aktivë</string>
<string name="a11y_poll_winner_option">mundësia fituese</string>
<string name="room_profile_section_more_polls">Historik pyetësorësh</string>
</resources>

View file

@ -3002,4 +3002,13 @@
<string name="set_link_link">Посилання</string>
<string name="set_link_text">Текст</string>
<string name="rich_text_editor_link">Налаштувати посилання</string>
<string name="settings_access_token_summary">Ваш токен доступу надає повний доступ до вашого облікового запису. Не передавайте його нікому.</string>
<string name="settings_access_token">Токен доступу</string>
<string name="rich_text_editor_bullet_list">Перемкнути на маркований список</string>
<string name="rich_text_editor_numbered_list">Перемкнути на нумерований список</string>
<string name="room_polls_ended_no_item">У цій кімнаті ще не проводилися опитування</string>
<string name="room_polls_ended">Минулі опитування</string>
<string name="room_polls_active_no_item">У цій кімнаті немає активних опитувань</string>
<string name="room_polls_active">Активні опитування</string>
<string name="room_profile_section_more_polls">Історія опитувань</string>
</resources>

View file

@ -2834,4 +2834,13 @@
<string name="set_link_link">連結</string>
<string name="set_link_text">文字</string>
<string name="rich_text_editor_link">設定連結</string>
<string name="settings_access_token_summary">您的存取權杖可以完整存取您的帳號。不要將其與其他人分享。</string>
<string name="settings_access_token">存取權杖</string>
<string name="rich_text_editor_bullet_list">切換項目符號清單</string>
<string name="rich_text_editor_numbered_list">切換編號清單</string>
<string name="room_polls_ended_no_item">此聊天室沒有過去的投票</string>
<string name="room_polls_ended">過去的投票</string>
<string name="room_polls_active_no_item">此聊天室沒有正在進行的投票</string>
<string name="room_polls_active">進行中的投票</string>
<string name="room_profile_section_more_polls">投票歷史紀錄</string>
</resources>

View file

@ -794,6 +794,7 @@
<string name="thread_list_modal_my_threads_subtitle">Shows all threads youve participated in</string>
<string name="thread_list_empty_title">Keep discussions organized with threads</string>
<string name="thread_list_empty_subtitle">Threads help keep your conversations on-topic and easy to track.</string>
<string name="thread_list_not_available">You\'re homeserver does not support listing threads yet.</string>
<!-- Parameter %s will be replaced by the value of string reply_in_thread -->
<string name="thread_list_empty_notice">Tip: Long tap a message and use “%s”.</string>
<string name="search_thread_from_a_thread">From a Thread</string>
@ -3177,7 +3178,8 @@
<item quantity="other">Final result based on %1$d votes</item>
</plurals>
<string name="poll_end_action">End poll</string>
<string name="a11y_poll_winner_option">winner option</string>
<!-- TODO TO BE REMOVED -->
<string name="a11y_poll_winner_option" tools:ignore="UnusedResources">winner option</string>
<string name="end_poll_confirmation_title">End this poll?</string>
<string name="end_poll_confirmation_description">This will stop people from being able to vote and will display the final results of the poll.</string>
<string name="end_poll_confirmation_approve_button">End poll</string>
@ -3191,6 +3193,7 @@
<string name="open_poll_option_description">Voters see results as soon as they have voted</string>
<string name="closed_poll_option_title">Closed poll</string>
<string name="closed_poll_option_description">Results are only revealed when you end the poll</string>
<string name="ended_poll_indicator">Ended the poll.</string>
<string name="room_polls_active">Active polls</string>
<string name="room_polls_active_no_item">There are no active polls in this room</string>
<string name="room_polls_ended">Past polls</string>
@ -3508,6 +3511,9 @@
<string name="message_reply_to_sender_sent_video">sent a video.</string>
<string name="message_reply_to_sender_sent_sticker">sent a sticker.</string>
<string name="message_reply_to_sender_created_poll">created a poll.</string>
<string name="message_reply_to_sender_ended_poll">ended a poll.</string>
<string name="message_reply_to_poll_preview">Poll</string>
<string name="message_reply_to_ended_poll_preview">Ended poll</string>
<string name="settings_access_token">Access Token</string>
<string name="settings_access_token_summary">Your access token gives full access to your account. Do not share it with anyone.</string>

View file

@ -22,6 +22,7 @@
<item name="android:clipToPadding">false</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">?vctr_message_text_color</item>
<item name="lineHeight">20sp</item>
</style>
</resources>

View file

@ -62,7 +62,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.5.20\""
buildConfigField "String", "SDK_VERSION", "\"1.5.22\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""

View file

@ -25,6 +25,9 @@ import java.io.IOException
import java.net.UnknownHostException
import javax.net.ssl.HttpsURLConnection
fun Throwable.is400() = this is Failure.ServerError &&
httpCode == HttpsURLConnection.HTTP_BAD_REQUEST
fun Throwable.is401() = this is Failure.ServerError &&
httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED && /* 401 */
error.code == MatrixError.M_UNAUTHORIZED

View file

@ -248,7 +248,7 @@ data class Event(
if (isRedacted()) return "Message removed"
val text = getDecryptedValue() ?: run {
if (isPoll()) {
return getPollQuestion() ?: "created a poll."
return getTextSummaryForPoll()
}
return null
}
@ -261,13 +261,23 @@ data class Event(
isImageMessage() -> "sent an image."
isVideoMessage() -> "sent a video."
isSticker() -> "sent a sticker."
isPoll() -> getPollQuestion() ?: "created a poll."
isPoll() -> getTextSummaryForPoll()
isLiveLocation() -> "Live location."
isLocationMessage() -> "has shared their location."
else -> text
}
}
private fun getTextSummaryForPoll(): String? {
val pollQuestion = getPollQuestion()
return when {
pollQuestion != null -> pollQuestion
isPollStart() -> "created a poll."
isPollEnd() -> "ended a poll."
else -> null
}
}
private fun Event.isQuote(): Boolean {
if (isReplyRenderedInThread()) return false
return getDecryptedValue("formatted_body")?.contains("<blockquote>") ?: false

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
/**
@ -25,5 +26,12 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon
*/
@JsonClass(generateAdapter = true)
data class MessageEndPollContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? = null
)
/**
* Local message type, not from server.
*/
@Transient
override val msgType: String = MessageType.MSGTYPE_POLL_END,
@Json(name = "body") override val body: String = "",
@Json(name = "m.new_content") override val newContent: Content? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null
) : MessageContent

View file

@ -36,6 +36,7 @@ object MessageType {
// Because poll events are not message events and they don't have msgtype field
const val MSGTYPE_POLL_START = "org.matrix.android.sdk.poll.start"
const val MSGTYPE_POLL_RESPONSE = "org.matrix.android.sdk.poll.response"
const val MSGTYPE_POLL_END = "org.matrix.android.sdk.poll.end"
const val MSGTYPE_CONFETTI = "nic.custom.confetti"
const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall"

View file

@ -19,5 +19,4 @@ package org.matrix.android.sdk.api.session.room.threads
sealed class FetchThreadsResult {
data class ShouldFetchMore(val nextBatch: String) : FetchThreadsResult()
object ReachedEnd : FetchThreadsResult()
object Failed : FetchThreadsResult()
}

View file

@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.room.threads.model.ThreadSummary
* This interface defines methods to interact with thread related features.
* It's the dynamic threads implementation and the homeserver must return
* a capability entry for threads. If the server do not support m.thread
* then [ThreadsLocalService] should be used instead
* then [org.matrix.android.sdk.api.session.room.threads.local.ThreadsLocalService] should be used instead
*/
interface ThreadsService {

View file

@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoCo
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
@ -148,6 +149,7 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
// so toModel<MessageContent> won't parse them correctly
// It's discriminated on event type instead. Maybe it shouldn't be MessageContent at all to avoid confusion?
in EventType.POLL_START.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>()
in EventType.POLL_END.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageEndPollContent>()
in EventType.STATE_ROOM_BEACON_INFO.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconInfoContent>()
in EventType.BEACON_LOCATION_DATA.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconLocationDataContent>()
else -> (getLastEditNewContent() ?: root.getClearContent()).toModel()

View file

@ -69,7 +69,7 @@ internal class DefaultLoginWizard(
)
} else {
PasswordLoginParams.userIdentifier(
user = login,
user = login.trim(),
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId

View file

@ -16,7 +16,6 @@
package org.matrix.android.sdk.internal.di
import androidx.annotation.Nullable
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.Moshi
@ -28,7 +27,6 @@ import java.lang.reflect.Type
internal annotation class SerializeNulls {
companion object {
val JSON_ADAPTER_FACTORY: JsonAdapter.Factory = object : JsonAdapter.Factory {
@Nullable
override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? {
val nextAnnotations = Types.nextAnnotations(annotations, SerializeNulls::class.java)
?: return null

View file

@ -16,7 +16,6 @@
package org.matrix.android.sdk.internal.network.interceptors
import androidx.annotation.NonNull
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONArray
import org.json.JSONException
@ -38,7 +37,7 @@ internal class FormattedJsonHttpLogger(
* @param message
*/
@Synchronized
override fun log(@NonNull message: String) {
override fun log(message: String) {
Timber.v(message)
// Try to log formatted Json only if there is a chance that [message] contains Json.

View file

@ -16,7 +16,6 @@
package org.matrix.android.sdk.internal.network.parsing
import androidx.annotation.Nullable
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
@ -32,14 +31,12 @@ internal interface CheckNumberType {
companion object {
val JSON_ADAPTER_FACTORY = object : JsonAdapter.Factory {
@Nullable
override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? {
if (type !== Any::class.java) {
return null
}
val delegate: JsonAdapter<Any> = moshi.nextAdapter(this, Any::class.java, emptySet())
return object : JsonAdapter<Any?>() {
@Nullable
@Throws(IOException::class)
override fun fromJson(reader: JsonReader): Any? {
return if (reader.peek() !== JsonReader.Token.NUMBER) {

View file

@ -30,10 +30,4 @@ internal data class GetPushRulesResponse(
*/
@Json(name = "global")
val global: RuleSet,
/**
* Device specific rules, apply only to current device.
*/
@Json(name = "device")
val device: RuleSet? = null
)

View file

@ -42,7 +42,6 @@ internal class DefaultSavePushRulesTask @Inject constructor(@SessionDatabase pri
.findAll()
.forEach { it.deleteOnCascade() }
// Save only global rules for the moment
val globalRules = params.pushRules.global
val content = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.CONTENT }

View file

@ -77,6 +77,7 @@
<issue id="UseValueOf" severity="error" />
<issue id="ObsoleteSdkInt" severity="error" />
<issue id="Recycle" severity="error" />
<issue id="KotlinNullnessAnnotation" severity="error" />
<issue id="KotlinPropertyAccess" severity="error" />
<issue id="DefaultLocale" severity="error" />
<issue id="CheckResult" severity="error" />

View file

@ -87,6 +87,14 @@ fi
printf "OK\n"
printf "\n================================================================================\n"
printf "Ensuring main and develop branches are up to date...\n"
git checkout main
git pull
git checkout develop
git pull
printf "\n================================================================================\n"
# Guessing version to propose a default version
versionMajorCandidate=`grep "ext.versionMajor" ./vector-app/build.gradle | cut -d " " -f3`
@ -103,14 +111,6 @@ versionMinor=`echo ${version} | cut -d "." -f2`
versionPatch=`echo ${version} | cut -d "." -f3`
nextPatchVersion=$((versionPatch + 2))
printf "\n================================================================================\n"
printf "Ensuring main and develop branches are up to date...\n"
git checkout main
git pull
git checkout develop
git pull
printf "\n================================================================================\n"
printf "Starting the release ${version}\n"
git flow release start ${version}
@ -190,6 +190,9 @@ yes | towncrier build --version "v${version}"
printf "\n================================================================================\n"
read -p "Check the file CHANGES.md consistency. It's possible to reorder items (most important changes first) or change their section if relevant. Also an opportunity to fix some typo, or rewrite things. Do not commit your change. Press enter when it's done."
# Get the changes to use it to create the GitHub release
changelogUrlEncoded=`git diff CHANGES.md | grep ^+ | tail -n +2 | cut -c2- | jq -sRr @uri | sed s/\(/%28/g | sed s/\)/%29/g`
printf "\n================================================================================\n"
printf "Committing...\n"
git commit -a -m "Changelog for version ${version}"
@ -263,7 +266,7 @@ else
fi
printf "\n================================================================================\n"
printf "Wait for the GitHub action https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Amain to build the 'main' branch.\n"
printf "Wait for the GitHub action https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%%3Amain to build the 'main' branch.\n"
read -p "After GHA is finished, please enter the artifact URL (for 'vector-gplay-release-unsigned'): " artifactUrl
printf "\n================================================================================\n"
@ -354,14 +357,19 @@ apkPath="${targetPath}/vector-gplay-arm64-v8a-release-signed.apk"
adb -d install ${apkPath}
read -p "Please run the APK on your phone to check that the upgrade went well (no init sync, etc.). Press enter when it's done."
# TODO Get the block to copy from towncrier earlier (be may be edited by the release manager)?
read -p "Create the release on gitHub from the tag https://github.com/vector-im/element-android/tags, copy paste the block from the file CHANGES.md. Press enter when it's done."
read -p "Add the 4 signed APKs to the GitHub release. They are located at ${targetPath}. Press enter when it's done."
printf "\n================================================================================\n"
githubCreateReleaseLink="https://github.com/vector-im/element-android/releases/new?tag=v${version}&title=Element%20Android%20v${version}&body=${changelogUrlEncoded}"
printf "Creating the release on gitHub.\n"
printf -- "Open this link: %s\n" ${githubCreateReleaseLink}
printf "Then\n"
printf " - click on the 'Generate releases notes' button\n"
printf " - Add the 4 signed APKs to the GitHub release. They are located at ${targetPath}\n"
read -p ". Press enter when it's done. "
printf "\n================================================================================\n"
printf "Message for the Android internal room:\n\n"
message="@room Element Android ${version} is ready to be tested. You can get if from https://github.com/vector-im/element-android/releases/tag/v${version}. Please report any feedback here. Thanks!"
message="@room Element Android ${version} is ready to be tested. You can get it from https://github.com/vector-im/element-android/releases/tag/v${version}. Please report any feedback here. Thanks!"
printf "${message}\n\n"
if [[ -z "${elementBotToken}" ]]; then

View file

@ -37,7 +37,7 @@ ext.versionMinor = 5
// Note: even values are reserved for regular release, odd values for hotfix release.
// When creating a hotfix, you should decrease the value, since the current value
// is the value for the next regular release.
ext.versionPatch = 20
ext.versionPatch = 22
static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'

View file

@ -132,7 +132,7 @@ dependencies {
implementation libs.androidx.biometric
api "org.threeten:threetenbp:1.4.0:no-tzdb"
api "com.gabrielittner.threetenbp:lazythreetenbp:0.12.0"
api "com.gabrielittner.threetenbp:lazythreetenbp:0.13.0"
implementation libs.squareup.moshi
kapt libs.squareup.moshiKotlin

View file

@ -27,7 +27,7 @@ import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
fun TimelineEvent.canReact(): Boolean {
// Only event of type EventType.MESSAGE, EventType.STICKER and EventType.POLL_START are supported for the moment
return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values &&
return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values + EventType.POLL_END.values &&
root.sendState == SendState.SYNCED &&
!root.isRedacted()
}

View file

@ -41,6 +41,7 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.preference.PreferenceManager
import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.MavericksView
@ -91,6 +92,7 @@ import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.themes.ThemeUtils
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.GlobalError
@ -123,14 +125,20 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
protected val viewModelProvider
get() = ViewModelProvider(this, viewModelFactory)
fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
.stream()
.onEach {
hideWaitingView()
observer(it)
}
.launchIn(lifecycleScope)
fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(
observer: (T) -> Unit,
) {
val tag = this@VectorBaseActivity::class.simpleName.toString()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewEvents
.stream(tag)
.collect {
hideWaitingView()
observer(it)
}
}
}
}
var toolbar: ToolbarConfig? = null

View file

@ -26,8 +26,10 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.CallSuper
import androidx.annotation.FloatRange
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.MavericksView
import com.google.android.material.bottomsheet.BottomSheetBehavior
@ -43,6 +45,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
import io.github.hyuwah.draggableviewlib.Utils
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
@ -199,12 +202,18 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
* ViewEvents
* ========================================================================================== */
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
.stream()
.onEach {
observer(it)
}
.launchIn(viewLifecycleOwner.lifecycleScope)
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(
observer: (T) -> Unit,
) {
val tag = this@VectorBaseBottomSheetDialogFragment::class.simpleName.toString()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewEvents
.stream(tag)
.collect {
observer(it)
}
}
}
}
}

View file

@ -23,8 +23,10 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.MavericksView
import dagger.hilt.android.EntryPointAccessors
@ -37,6 +39,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.themes.ThemeUtils
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
@ -145,11 +148,15 @@ abstract class VectorBaseDialogFragment<VB : ViewBinding> : DialogFragment(), Ma
* ========================================================================================== */
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
.stream()
.onEach {
observer(it)
}
.launchIn(viewLifecycleOwner.lifecycleScope)
val tag = this@VectorBaseDialogFragment::class.simpleName.toString()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewEvents
.stream(tag)
.collect {
observer(it)
}
}
}
}
}

View file

@ -34,6 +34,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.MavericksView
import com.bumptech.glide.util.Util.assertMainThread
@ -53,6 +54,7 @@ import im.vector.app.features.navigation.Navigator
import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
@ -272,14 +274,20 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
* ViewEvents
* ========================================================================================== */
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
.stream()
.onEach {
dismissLoadingDialog()
observer(it)
}
.launchIn(viewLifecycleOwner.lifecycleScope)
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(
observer: (T) -> Unit,
) {
val tag = this@VectorBaseFragment::class.simpleName.toString()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewEvents
.stream(tag)
.collect {
dismissLoadingDialog()
observer(it)
}
}
}
}
/* ==========================================================================================

View file

@ -18,15 +18,16 @@ package im.vector.app.core.platform
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.MavericksViewModel
import im.vector.app.core.utils.DataSource
import im.vector.app.core.utils.PublishDataSource
import im.vector.app.core.utils.EventQueue
import im.vector.app.core.utils.SharedEvents
abstract class VectorViewModel<S : MavericksState, VA : VectorViewModelAction, VE : VectorViewEvents>(initialState: S) :
MavericksViewModel<S>(initialState) {
// Used to post transient events to the View
protected val _viewEvents = PublishDataSource<VE>()
val viewEvents: DataSource<VE> = _viewEvents
protected val _viewEvents = EventQueue<VE>(capacity = 64)
val viewEvents: SharedEvents<VE>
get() = _viewEvents
abstract fun handle(action: VA)
}

View file

@ -18,7 +18,6 @@ package im.vector.app.core.resources
import android.content.res.Resources
import androidx.annotation.ArrayRes
import androidx.annotation.NonNull
import javax.inject.Inject
class StringArrayProvider @Inject constructor(private val resources: Resources) {
@ -31,7 +30,6 @@ class StringArrayProvider @Inject constructor(private val resources: Resources)
* @return The string array associated with the resource, stripped of styled
* text information.
*/
@NonNull
fun getStringArray(@ArrayRes resId: Int): Array<String> {
return resources.getStringArray(resId)
}

View file

@ -17,7 +17,6 @@
package im.vector.app.core.resources
import android.content.res.Resources
import androidx.annotation.NonNull
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import javax.inject.Inject
@ -32,7 +31,6 @@ class StringProvider @Inject constructor(private val resources: Resources) {
* @return The string data associated with the resource, stripped of styled
* text information.
*/
@NonNull
fun getString(@StringRes resId: Int): String {
return resources.getString(resId)
}
@ -48,12 +46,10 @@ class StringProvider @Inject constructor(private val resources: Resources) {
* @return The string data associated with the resource, formatted and
* stripped of styled text information.
*/
@NonNull
fun getString(@StringRes resId: Int, vararg formatArgs: Any?): String {
return resources.getString(resId, *formatArgs)
}
@NonNull
fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String {
return resources.getQuantityString(resId, quantity, *formatArgs)
}

View file

@ -0,0 +1,65 @@
/*
* Copyright 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.utils
import im.vector.app.core.platform.VectorViewEvents
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.transform
import java.util.concurrent.CopyOnWriteArraySet
interface SharedEvents<out T : VectorViewEvents> {
fun stream(consumerId: String): Flow<T>
}
class EventQueue<T : VectorViewEvents>(capacity: Int) : SharedEvents<T> {
private val innerQueue = MutableSharedFlow<OneTimeEvent<T>>(replay = capacity)
fun post(event: T) {
innerQueue.tryEmit(OneTimeEvent(event))
}
override fun stream(consumerId: String): Flow<T> = innerQueue
.onEach {
// Ensure that buffered Events will not be sent again to new subscribers.
innerQueue.resetReplayCache()
}
.filterNotHandledBy(consumerId)
}
/**
* Event designed to be delivered only once to a concrete entity,
* but it can also be delivered to multiple different entities.
*
* Keeps track of who has already handled its content.
*/
private class OneTimeEvent<out T : VectorViewEvents>(private val content: T) {
private val handlers = CopyOnWriteArraySet<String>()
/**
* @param asker Used to identify, whether this "asker" has already handled this Event.
* @return Event content or null if it has been already handled by asker
*/
fun getIfNotHandled(asker: String): T? = if (handlers.add(asker)) content else null
}
private fun <T : VectorViewEvents> Flow<OneTimeEvent<T>>.filterNotHandledBy(consumerId: String): Flow<T> = transform { event ->
event.getIfNotHandled(consumerId)?.let { emit(it) }
}

View file

@ -55,8 +55,6 @@ import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.ui.UiStateRepository
import im.vector.lib.core.utils.compat.getParcelableExtraCompat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
@ -142,9 +140,9 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
startAppViewModel.onEach {
renderState(it)
}
startAppViewModel.viewEvents.stream()
.onEach(::handleViewEvents)
.launchIn(lifecycleScope)
startAppViewModel.observeViewEvents {
handleViewEvents(it)
}
startAppViewModel.handle(StartAppAction.StartApp)
}

View file

@ -59,7 +59,7 @@ class SharedSecureStorageActivity :
views.toolbar.visibility = View.GONE
viewModel.observeViewEvents { observeViewEvents(it) }
viewModel.observeViewEvents { onViewEvents(it) }
viewModel.onEach { renderState(it) }
}
@ -85,7 +85,7 @@ class SharedSecureStorageActivity :
showFragment(fragment)
}
private fun observeViewEvents(it: SharedSecureStorageViewEvent?) {
private fun onViewEvents(it: SharedSecureStorageViewEvent) {
when (it) {
is SharedSecureStorageViewEvent.Dismiss -> {
finish()

View file

@ -44,6 +44,7 @@ import org.commonmark.parser.Parser
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
@ -181,6 +182,7 @@ class PlainTextComposerLayout @JvmOverloads constructor(
is MessageAudioContent -> getAudioContentBodyText(messageContent)
is MessagePollContent -> messageContent.getBestPollCreationInfo()?.question?.getBestQuestion()
is MessageBeaconInfoContent -> resources.getString(R.string.live_location_description)
is MessageEndPollContent -> resources.getString(R.string.message_reply_to_ended_poll_preview)
else -> messageContent?.body.orEmpty()
}
var formattedBody: CharSequence? = null

View file

@ -25,8 +25,14 @@ import javax.inject.Inject
class CheckIfCanReplyEventUseCase @Inject constructor() {
fun execute(event: TimelineEvent, messageContent: MessageContent?, actionPermissions: ActionPermissions): Boolean {
// Only EventType.MESSAGE, EventType.POLL_START and EventType.STATE_ROOM_BEACON_INFO event types are supported for the moment
if (event.root.getClearType() !in EventType.STATE_ROOM_BEACON_INFO.values + EventType.POLL_START.values + EventType.MESSAGE) return false
// Only EventType.MESSAGE, EventType.POLL_START, EventType.POLL_END and EventType.STATE_ROOM_BEACON_INFO event types are supported for the moment
if (event.root.getClearType() !in
EventType.STATE_ROOM_BEACON_INFO.values +
EventType.POLL_START.values +
EventType.POLL_END.values +
EventType.MESSAGE
) return false
if (!actionPermissions.canSendMessage) return false
return when (messageContent?.msgType) {
MessageType.MSGTYPE_TEXT,
@ -37,6 +43,7 @@ class CheckIfCanReplyEventUseCase @Inject constructor() {
MessageType.MSGTYPE_AUDIO,
MessageType.MSGTYPE_FILE,
MessageType.MSGTYPE_POLL_START,
MessageType.MSGTYPE_POLL_END,
MessageType.MSGTYPE_BEACON_INFO,
MessageType.MSGTYPE_LOCATION -> true
else -> false

View file

@ -498,6 +498,7 @@ class MessageActionsViewModel @AssistedInject constructor(
MessageType.MSGTYPE_AUDIO,
MessageType.MSGTYPE_FILE,
MessageType.MSGTYPE_POLL_START,
MessageType.MSGTYPE_POLL_END,
MessageType.MSGTYPE_STICKER_LOCAL -> event.root.threadDetails?.isRootThread ?: false
else -> false
}
@ -529,8 +530,8 @@ class MessageActionsViewModel @AssistedInject constructor(
}
private fun canViewReactions(event: TimelineEvent): Boolean {
// Only event of type EventType.MESSAGE, EventType.STICKER and EventType.POLL_START are supported for the moment
if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values) return false
// Only event of type EventType.MESSAGE, EventType.STICKER, EventType.POLL_START, EventType.POLL_END are supported for the moment
if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START.values + EventType.POLL_END.values) return false
return event.annotations?.reactionsSummary?.isNotEmpty() ?: false
}

View file

@ -91,11 +91,13 @@ import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.isThread
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
import org.matrix.android.sdk.api.session.room.model.message.MessageEmoteContent
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
@ -109,8 +111,10 @@ import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
import org.matrix.android.sdk.api.util.MimeTypes
import timber.log.Timber
import javax.inject.Inject
class MessageItemFactory @Inject constructor(
@ -202,7 +206,8 @@ class MessageItemFactory @Inject constructor(
is MessageFileContent -> buildFileMessageItem(messageContent, highlight, attributes)
is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, attributes)
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes, isEnded = false)
is MessageEndPollContent -> buildEndedPollItem(event.getRelationContent()?.eventId, informationData, highlight, callback, attributes)
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(event, highlight, attributes)
is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes)
@ -245,6 +250,7 @@ class MessageItemFactory @Inject constructor(
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
isEnded: Boolean,
): PollItem {
val pollViewState = pollItemViewStateFactory.create(pollContent, informationData)
@ -256,11 +262,35 @@ class MessageItemFactory @Inject constructor(
.votesStatus(pollViewState.votesStatus)
.optionViewStates(pollViewState.optionViewStates.orEmpty())
.edited(informationData.hasBeenEdited)
.ended(isEnded)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.callback(callback)
}
private fun buildEndedPollItem(
pollStartEventId: String?,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): PollItem? {
pollStartEventId ?: return null.also {
Timber.e("### buildEndedPollItem. Cannot render poll end event because poll start event id is null")
}
val pollStartEvent = session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>() ?: return null
return buildPollItem(
pollContent,
informationData,
highlight,
callback,
attributes,
isEnded = true
)
}
private fun createPollQuestion(
informationData: MessageInformationData,
question: String,

View file

@ -102,6 +102,7 @@ class TimelineItemFactory @Inject constructor(
// Message itemsX
EventType.STICKER,
in EventType.POLL_START.values,
in EventType.POLL_END.values,
EventType.MESSAGE -> messageItemFactory.create(params)
EventType.REDACTION,
EventType.KEY_VERIFICATION_ACCEPT,
@ -114,8 +115,7 @@ class TimelineItemFactory @Inject constructor(
EventType.CALL_SELECT_ANSWER,
EventType.CALL_NEGOTIATE,
EventType.REACTION,
in EventType.POLL_RESPONSE.values,
in EventType.POLL_END.values -> noticeItemFactory.create(params)
in EventType.POLL_RESPONSE.values -> noticeItemFactory.create(params)
in EventType.BEACON_LOCATION_DATA.values -> {
if (event.root.isRedacted()) {
messageItemFactory.create(params)

View file

@ -17,11 +17,14 @@
package im.vector.app.features.home.room.detail.timeline.format
import android.content.Context
import im.vector.app.R
import im.vector.app.core.utils.TextUtils
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.isAudioMessage
import org.matrix.android.sdk.api.session.events.model.isFileMessage
import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isPollEnd
import org.matrix.android.sdk.api.session.events.model.isPollStart
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
@ -51,10 +54,16 @@ class EventDetailsFormatter @Inject constructor(
event.isVideoMessage() -> formatForVideoMessage(event)
event.isAudioMessage() -> formatForAudioMessage(event)
event.isFileMessage() -> formatForFileMessage(event)
event.isPollStart() -> formatPollMessage()
event.isPollEnd() -> formatPollEndMessage()
else -> null
}
}
private fun formatPollMessage() = context.getString(R.string.message_reply_to_poll_preview)
private fun formatPollEndMessage() = context.getString(R.string.message_reply_to_ended_poll_preview)
/**
* Example: "1024 x 720 - 670 kB".
*/

View file

@ -23,8 +23,6 @@ import im.vector.app.core.extensions.localDateTime
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactoryParams
import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
import im.vector.app.features.home.room.detail.timeline.item.PollVoteSummaryData
import im.vector.app.features.home.room.detail.timeline.item.ReferencesInfoData
import im.vector.app.features.home.room.detail.timeline.item.SendStateDecoration
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayoutFactory
@ -54,7 +52,8 @@ class MessageInformationDataFactory @Inject constructor(
private val session: Session,
private val dateFormatter: VectorDateFormatter,
private val messageLayoutFactory: TimelineMessageLayoutFactory,
private val reactionsSummaryFactory: ReactionsSummaryFactory
private val reactionsSummaryFactory: ReactionsSummaryFactory,
private val pollResponseDataFactory: PollResponseDataFactory,
) {
fun create(params: TimelineItemFactoryParams): MessageInformationData {
@ -99,20 +98,7 @@ class MessageInformationDataFactory @Inject constructor(
memberName = event.senderInfo.disambiguatedDisplayName,
messageLayout = messageLayout,
reactionsSummary = reactionsSummaryFactory.create(event),
pollResponseAggregatedSummary = event.annotations?.pollResponseSummary?.let {
PollResponseData(
myVote = it.aggregatedContent?.myVote,
isClosed = it.closedTime != null,
votes = it.aggregatedContent?.votesSummary?.mapValues { votesSummary ->
PollVoteSummaryData(
total = votesSummary.value.total,
percentage = votesSummary.value.percentage
)
},
winnerVoteCount = it.aggregatedContent?.winnerVoteCount ?: 0,
totalVotes = it.aggregatedContent?.totalVotes ?: 0
)
},
pollResponseAggregatedSummary = pollResponseDataFactory.create(event),
hasBeenEdited = event.hasBeenEdited(),
hasPendingEdits = event.annotations?.editSummary?.localEchos?.any() ?: false,
referencesInfoData = event.annotations?.referencesAggregatedSummary?.let { referencesAggregatedSummary ->

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2023 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.home.room.detail.timeline.helper
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
import im.vector.app.features.home.room.detail.timeline.item.PollVoteSummaryData
import org.matrix.android.sdk.api.session.events.model.getRelationContent
import org.matrix.android.sdk.api.session.events.model.isPollEnd
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.PollResponseAggregatedSummary
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import timber.log.Timber
import javax.inject.Inject
class PollResponseDataFactory @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
) {
fun create(event: TimelineEvent): PollResponseData? {
val pollResponseSummary = getPollResponseSummary(event)
return pollResponseSummary?.let {
PollResponseData(
myVote = it.aggregatedContent?.myVote,
isClosed = it.closedTime != null,
votes = it.aggregatedContent?.votesSummary?.mapValues { votesSummary ->
PollVoteSummaryData(
total = votesSummary.value.total,
percentage = votesSummary.value.percentage
)
},
winnerVoteCount = it.aggregatedContent?.winnerVoteCount ?: 0,
totalVotes = it.aggregatedContent?.totalVotes ?: 0
)
}
}
private fun getPollResponseSummary(event: TimelineEvent): PollResponseAggregatedSummary? {
return if (event.root.isPollEnd()) {
val pollStartEventId = event.root.getRelationContent()?.eventId
if (pollStartEventId.isNullOrEmpty()) {
Timber.e("### Cannot render poll end event because poll start event id is null")
null
} else {
activeSessionHolder
.getSafeActiveSession()
?.roomService()
?.getRoom(event.roomId)
?.getTimelineEvent(pollStartEventId)
?.annotations
?.pollResponseSummary
}
} else {
event.annotations?.pollResponseSummary
}
}
}

View file

@ -55,6 +55,7 @@ object TimelineDisplayableEvents {
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO,
) +
EventType.POLL_START.values +
EventType.POLL_END.values +
EventType.STATE_ROOM_BEACON_INFO.values +
EventType.BEACON_LOCATION_DATA.values
}

View file

@ -85,7 +85,7 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
if (useBigFont) {
holder.messageView.textSize = 44F
} else {
holder.messageView.textSize = 14F
holder.messageView.textSize = 15.5F
}
if (searchForPills) {
message?.charSequence?.findPillsAndProcess(coroutineScope) {

View file

@ -19,6 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.item
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.children
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
@ -50,6 +51,9 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
@EpoxyAttribute
lateinit var optionViewStates: List<PollOptionViewState>
@EpoxyAttribute
var ended: Boolean = false
override fun getViewStubId() = STUB_ID
override fun bind(holder: Holder) {
@ -75,6 +79,8 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
it.setOnClickListener { onPollItemClick(optionViewState) }
}
}
holder.endedPollTextView.isVisible = ended
}
private fun onPollItemClick(optionViewState: PollOptionViewState) {
@ -89,6 +95,7 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
val questionTextView by bind<TextView>(R.id.questionTextView)
val optionsContainer by bind<LinearLayout>(R.id.optionsContainer)
val votesStatusTextView by bind<TextView>(R.id.optionsVotesStatusTextView)
val endedPollTextView by bind<TextView>(R.id.endedPollTextView)
}
companion object {

View file

@ -25,6 +25,7 @@ import androidx.core.view.isVisible
import im.vector.app.R
import im.vector.app.core.extensions.setAttributeTintedImageResource
import im.vector.app.databinding.ItemPollOptionBinding
import im.vector.app.features.themes.ThemeUtils
class PollOptionView @JvmOverloads constructor(
context: Context,
@ -53,35 +54,40 @@ class PollOptionView @JvmOverloads constructor(
private fun renderPollSending() {
views.optionCheckImageView.isVisible = false
views.optionWinnerImageView.isVisible = false
views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
hideVotes()
renderVoteSelection(false)
}
private fun renderPollEnded(state: PollOptionViewState.PollEnded) {
views.optionCheckImageView.isVisible = false
views.optionWinnerImageView.isVisible = state.isWinner
val drawableStart = if (state.isWinner) R.drawable.ic_poll_winner else 0
views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, 0, 0, 0)
views.optionVoteCountTextView.setTextColor(
if (state.isWinner) ThemeUtils.getColor(context, R.attr.colorPrimary)
else ThemeUtils.getColor(context, R.attr.vctr_content_secondary)
)
showVotes(state.voteCount, state.votePercentage)
renderVoteSelection(state.isWinner)
}
private fun renderPollReady() {
views.optionCheckImageView.isVisible = true
views.optionWinnerImageView.isVisible = false
views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
hideVotes()
renderVoteSelection(false)
}
private fun renderPollVoted(state: PollOptionViewState.PollVoted) {
views.optionCheckImageView.isVisible = true
views.optionWinnerImageView.isVisible = false
views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
showVotes(state.voteCount, state.votePercentage)
renderVoteSelection(state.isSelected)
}
private fun renderPollUndisclosed(state: PollOptionViewState.PollUndisclosed) {
views.optionCheckImageView.isVisible = true
views.optionWinnerImageView.isVisible = false
views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
hideVotes()
renderVoteSelection(state.isSelected)
}

View file

@ -25,6 +25,8 @@ import org.matrix.android.sdk.api.session.events.model.isFileMessage
import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isLiveLocation
import org.matrix.android.sdk.api.session.events.model.isPoll
import org.matrix.android.sdk.api.session.events.model.isPollEnd
import org.matrix.android.sdk.api.session.events.model.isPollStart
import org.matrix.android.sdk.api.session.events.model.isSticker
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
@ -93,10 +95,15 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor(
)
}
repliedToEvent.isPoll() -> {
val fallbackText = when {
repliedToEvent.isPollStart() -> stringProvider.getString(R.string.message_reply_to_sender_created_poll)
repliedToEvent.isPollEnd() -> stringProvider.getString(R.string.message_reply_to_sender_ended_poll)
else -> ""
}
matrixFormattedBody.replaceRange(
afterBreakingLineIndex,
endOfBlockQuoteIndex,
repliedToEvent.getPollQuestion() ?: stringProvider.getString(R.string.message_reply_to_sender_created_poll)
repliedToEvent.getPollQuestion() ?: fallbackText
)
}
repliedToEvent.isLiveLocation() -> {

View file

@ -50,6 +50,7 @@ class TimelineMessageLayoutFactory @Inject constructor(
EventType.STICKER,
) +
EventType.POLL_START.values +
EventType.POLL_END.values +
EventType.STATE_ROOM_BEACON_INFO.values
// Can't be rendered in bubbles, so get back to default layout

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 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.home.room.threads.list.viewmodel
import im.vector.app.core.platform.VectorViewModelAction
sealed interface ThreadListViewActions : VectorViewModelAction {
object TryAgain : ThreadListViewActions
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 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.home.room.threads.list.viewmodel
import im.vector.app.core.platform.VectorViewEvents
sealed interface ThreadListViewEvents : VectorViewEvents {
data class ShowError(val throwable: Throwable) : ThreadListViewEvents
}

Some files were not shown because too many files have changed in this diff Show more