Merge develop into feature/db_clean_up

This commit is contained in:
ganfra 2020-07-06 19:18:42 +02:00
commit 08cda2ee10
46 changed files with 213 additions and 296 deletions

View file

@ -10,6 +10,9 @@ Improvements 🙌:
Bugfix 🐛:
- Fix crash when coming from a notification (#1601)
- Fix Exception when importing keys (#1576)
- File isn't downloaded when another file with the same name already exists (#1578)
- saved images don't show up in gallery (#1324)
- Fix reply fallback leaking sender locale (#429)
Translations 🗣:
-
@ -18,7 +21,9 @@ SDK API changes ⚠️:
-
Build 🧱:
-
- Fix lint false-positive about WorkManger (#1012)
- Upgrade build-tools from 3.5.3 to 3.6.6
- Upgrade gradle from 5.4.1 to 5.6.4
Other changes:
-

View file

@ -10,7 +10,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.google.gms:google-services:4.3.2'
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

View file

@ -1,6 +1,6 @@
#Fri Sep 27 10:10:35 CEST 2019
#Thu Jul 02 12:33:07 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="im.vector.matrix.android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -8,11 +7,6 @@
<application android:networkSecurityConfig="@xml/network_security_config">
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
android:exported="false"
tools:node="remove" />
<!--
The SDK offers a secured File provider to access downloaded files.
Access to these file will be given via the FileService, with a temporary

View file

@ -98,6 +98,7 @@ import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.task.launchToCallback
import im.vector.matrix.android.internal.util.JsonCanonicalizer
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.fetchCopied
@ -340,7 +341,7 @@ internal class DefaultCryptoService @Inject constructor(
}
fun ensureDevice() {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
cryptoCoroutineScope.launchToCallback(coroutineDispatchers.crypto, NoOpMatrixCallback()) {
// Open the store
cryptoStore.open()
// TODO why do that everytime? we should mark that it was done

View file

@ -176,7 +176,6 @@ internal class LocalEchoEventFactory @Inject constructor(
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.root.getClearContent().toModel())
val replyFormatted = REPLY_PATTERN.format(
permalink,
stringProvider.getString(R.string.message_reply_to_prefix),
userLink,
originalEvent.senderInfo.disambiguatedDisplayName,
body.takeFormatted(),
@ -371,7 +370,6 @@ internal class LocalEchoEventFactory @Inject constructor(
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.root.getClearContent().toModel())
val replyFormatted = REPLY_PATTERN.format(
permalink,
stringProvider.getString(R.string.message_reply_to_prefix),
userLink,
userId,
body.takeFormatted(),
@ -433,10 +431,10 @@ internal class LocalEchoEventFactory @Inject constructor(
TextContent(content.body, formattedText)
}
}
MessageType.MSGTYPE_FILE -> return TextContent(stringProvider.getString(R.string.reply_to_a_file))
MessageType.MSGTYPE_AUDIO -> return TextContent(stringProvider.getString(R.string.reply_to_an_audio_file))
MessageType.MSGTYPE_IMAGE -> return TextContent(stringProvider.getString(R.string.reply_to_an_image))
MessageType.MSGTYPE_VIDEO -> return TextContent(stringProvider.getString(R.string.reply_to_a_video))
MessageType.MSGTYPE_FILE -> return TextContent("sent a file.")
MessageType.MSGTYPE_AUDIO -> return TextContent("sent an audio file.")
MessageType.MSGTYPE_IMAGE -> return TextContent("sent an image.")
MessageType.MSGTYPE_VIDEO -> return TextContent("sent a video.")
else -> return TextContent(content?.body ?: "")
}
}
@ -486,6 +484,6 @@ internal class LocalEchoEventFactory @Inject constructor(
// </blockquote>
// </mx-reply>
// No whitespace because currently breaks temporary formatted text to Span
const val REPLY_PATTERN = """<mx-reply><blockquote><a href="%s">%s</a><a href="%s">%s</a><br />%s</blockquote></mx-reply>%s"""
const val REPLY_PATTERN = """<mx-reply><blockquote><a href="%s">In reply to</a> <a href="%s">%s</a><br />%s</blockquote></mx-reply>%s"""
}
}

View file

@ -63,12 +63,6 @@
<string name="summary_user_sent_sticker">أرسل %1$s ملصقا.</string>
<string name="notice_avatar_changed_too">(تغيّرت الصورة أيضا)</string>
<string name="message_reply_to_prefix">ردا على</string>
<string name="reply_to_an_image">أرسل صورة.</string>
<string name="reply_to_a_video">أرسل فديوهًا.</string>
<string name="reply_to_an_audio_file">أرسل ملف صوت.</string>
<string name="reply_to_a_file">أرسل ملفًا.</string>
<string name="room_displayname_invite_from">دعوة من %s</string>
<string name="room_displayname_empty_room">غرفة فارغة</string>

View file

@ -52,8 +52,6 @@
<string name="notice_crypto_unable_to_decrypt">** Şifrəni aça bilmir: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Göndərənin cihazı bu mesaj üçün açarları bizə göndərməyib.</string>
<string name="message_reply_to_prefix">Cavab olaraq</string>
<string name="could_not_redact">Redaktə etmək olmur</string>
<string name="unable_to_send_message">Mesaj göndərmək olmur</string>
@ -69,11 +67,6 @@
<string name="medium_email">Elektron poçt ünvanı</string>
<string name="medium_phone_number">Telefon nömrəsi</string>
<string name="reply_to_an_image">şəkil göndərdi.</string>
<string name="reply_to_a_video">video göndərdi.</string>
<string name="reply_to_an_audio_file">səs faylı göndərdi.</string>
<string name="reply_to_a_file">fayl göndərdi.</string>
<string name="room_displayname_invite_from">%s-dən dəvət</string>
<string name="room_displayname_room_invite">Otağa dəvət</string>

View file

@ -63,13 +63,6 @@
<string name="summary_user_sent_sticker">%1$s изпрати стикер.</string>
<string name="message_reply_to_prefix">В отговор на</string>
<string name="reply_to_an_image">изпрати снимка.</string>
<string name="reply_to_a_video">изпрати видео.</string>
<string name="reply_to_an_audio_file">изпрати аудио файл.</string>
<string name="reply_to_a_file">изпрати файл.</string>
<string name="room_displayname_invite_from">Покана от %s</string>
<string name="room_displayname_room_invite">Покана за стая</string>
<string name="room_displayname_two_members">%1$s и %2$s</string>

View file

@ -76,11 +76,4 @@
<string name="summary_user_sent_sticker">%1$s ha enviat un adhesiu.</string>
<string name="message_reply_to_prefix">En resposta a</string>
<string name="reply_to_an_image">ha enviat una imatge.</string>
<string name="reply_to_a_video">ha enviat un vídeo.</string>
<string name="reply_to_an_audio_file">ha enviat un fitxer d\'àudio.</string>
<string name="reply_to_a_file">ha enviat un fitxer.</string>
</resources>

View file

@ -46,8 +46,6 @@
<string name="notice_crypto_unable_to_decrypt">** Nelze dešifrovat: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Odesílatelovo zařízení neposlalo klíče pro tuto zprávu.</string>
<string name="message_reply_to_prefix">V odpovědi na</string>
<string name="could_not_redact">Nelze vymazat</string>
<string name="unable_to_send_message">Zprávu nelze odeslat</string>
@ -63,11 +61,6 @@
<string name="medium_email">E-mailová adresa</string>
<string name="medium_phone_number">Telefonní číslo</string>
<string name="reply_to_an_image">odeslal obrázek.</string>
<string name="reply_to_a_video">odeslal video.</string>
<string name="reply_to_an_audio_file">odeslal zvukový soubor.</string>
<string name="reply_to_a_file">odeslal soubor.</string>
<string name="room_displayname_invite_from">Pozvání od %s</string>
<string name="room_displayname_room_invite">Pozvání do místnosti</string>

View file

@ -73,13 +73,6 @@
<string name="summary_user_sent_sticker">%1$s sandte einen Sticker.</string>
<string name="message_reply_to_prefix">Als Antwort auf</string>
<string name="reply_to_an_image">hat ein Bild gesendet.</string>
<string name="reply_to_a_video">hat ein Video gesendet.</string>
<string name="reply_to_an_audio_file">hat eine Audio-Datei gesendet.</string>
<string name="reply_to_a_file">sandte eine Datei.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Einladung von %s</string>
<string name="room_displayname_room_invite">Raumeinladung</string>

View file

@ -40,8 +40,6 @@
<string name="notice_crypto_unable_to_decrypt">** Αδυναμία αποκρυπτογράφησης: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Η συσκευή του/της αποστολέα δεν μας έχει στείλει τα κλειδιά για αυτό το μήνυμα.</string>
<string name="message_reply_to_prefix">Προς απάντηση στο</string>
<string name="unable_to_send_message">Αποτυχία αποστολής μηνύματος</string>
<string name="message_failed_to_upload">Αποτυχία αναφόρτωσης εικόνας</string>
@ -56,10 +54,6 @@
<string name="notice_voip_finished">Η VoIP διάσκεψη έληξε</string>
<string name="notice_room_join">Ο/Η %1$s εισήλθε στο δωμάτιο</string>
<string name="reply_to_an_image">έστειλε μία εικόνα.</string>
<string name="reply_to_a_video">έστειλε ένα βίντεο.</string>
<string name="reply_to_an_audio_file">έστειλε ένα αρχείο ήχου.</string>
<string name="reply_to_a_file">έστειλε ένα αρχείο.</string>
<string name="room_displayname_invite_from">Πρόσκληση από %s</string>
<string name="room_displayname_room_invite">Πρόσκληση στο δωμάτιο</string>

View file

@ -17,8 +17,6 @@
<string name="notice_crypto_unable_to_decrypt">** Ne eblas malĉifri: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">La aparato de la sendanto ne sendis al ni la ŝlosilojn por tiu mesaĝo.</string>
<string name="message_reply_to_prefix">Responde al</string>
<string name="summary_message">%1$s: %2$s</string>
<string name="notice_display_name_set">%1$s ŝanĝis sian vidigan nomon al %2$s</string>
<string name="notice_display_name_changed_from">%1$s ŝanĝis sian vidigan nomon de %2$s al %3$s</string>
@ -62,11 +60,6 @@
<string name="medium_email">Retpoŝtadreso</string>
<string name="medium_phone_number">Telefonnumero</string>
<string name="reply_to_an_image">sendis bildon.</string>
<string name="reply_to_a_video">sendis filmon.</string>
<string name="reply_to_an_audio_file">sendis sondosieron.</string>
<string name="reply_to_a_file">sendis dosieron.</string>
<string name="room_displayname_invite_from">Invito de %s</string>
<string name="room_displayname_room_invite">Ĉambra invito</string>

View file

@ -73,13 +73,6 @@
<string name="summary_user_sent_sticker">%1$s envió una calcomanía.</string>
<string name="message_reply_to_prefix">En respuesta a</string>
<string name="reply_to_an_image">envió una imagen.</string>
<string name="reply_to_a_video">envió un video.</string>
<string name="reply_to_an_audio_file">envió un archivo de audio.</string>
<string name="reply_to_a_file">envió un archivo.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Invitación de %s</string>
<string name="room_displayname_room_invite">Invitación de Sala</string>

View file

@ -73,13 +73,6 @@
<string name="summary_user_sent_sticker">%1$s envió una pegatina.</string>
<string name="message_reply_to_prefix">En respuesta a</string>
<string name="reply_to_an_image">envió una imagen.</string>
<string name="reply_to_a_video">envió un vídeo.</string>
<string name="reply_to_an_audio_file">envió un archivo de audio.</string>
<string name="reply_to_a_file">envió un archivo.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Invitación de %s</string>
<string name="room_displayname_room_invite">Invitación a Sala</string>

View file

@ -50,8 +50,6 @@
<string name="notice_crypto_unable_to_decrypt">** Ei õnnestu dekrüptida: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Sõnumi saatja seade ei ole selle sõnumi jaoks saatnud dekrüptimisvõtmeid.</string>
<string name="message_reply_to_prefix">Vastuseks kasutajale</string>
<string name="could_not_redact">Ei saanud muuta sõnumit</string>
<string name="unable_to_send_message">Sõnumi saatmine ei õnnestunud</string>
@ -67,11 +65,6 @@
<string name="medium_email">E-posti aadress</string>
<string name="medium_phone_number">Telefoninumber</string>
<string name="reply_to_an_image">saatis pildi.</string>
<string name="reply_to_a_video">saatis video.</string>
<string name="reply_to_an_audio_file">saatis helifaili.</string>
<string name="reply_to_a_file">saatis faili.</string>
<string name="room_displayname_invite_from">Kutse kasutajalt %s</string>
<string name="room_displayname_room_invite">Kutse jututuppa</string>

View file

@ -63,13 +63,6 @@
<string name="summary_user_sent_sticker">%1$s erabiltzaileak eranskailu bat bidali du.</string>
<string name="message_reply_to_prefix">Honi erantzunez</string>
<string name="reply_to_an_image">irudi bat bidali du.</string>
<string name="reply_to_a_video">bideo bat bidali du.</string>
<string name="reply_to_an_audio_file">audio fitxategi bat bidali du.</string>
<string name="reply_to_a_file">fitxategi bat bidali du.</string>
<string name="room_displayname_invite_from">%s gelarako gonbidapena</string>
<string name="room_displayname_room_invite">Gela gonbidapena</string>
<string name="room_displayname_two_members">%1$s eta %2$s</string>

View file

@ -51,8 +51,6 @@
<string name="notice_crypto_unable_to_decrypt">** ناتوان در رمزگشایی: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">دستگاه فرستنده، کلیدهای این پیام را برایمان نفرستاده است.</string>
<string name="message_reply_to_prefix">در پاسخ به</string>
<string name="unable_to_send_message">ناتوان در فرستادن پیام</string>
<string name="message_failed_to_upload">شکست در بارگذاری تصویر</string>
@ -67,11 +65,6 @@
<string name="medium_email">نشانی رایانامه</string>
<string name="medium_phone_number">شماره تلفن</string>
<string name="reply_to_an_image">تصویری فرستاد.</string>
<string name="reply_to_a_video">ویدیویی فرستاد.</string>
<string name="reply_to_an_audio_file">پرونده‌ای صوتی فرستاد.</string>
<string name="reply_to_a_file">پرونده‌ای فرستاد.</string>
<string name="room_displayname_invite_from">دعوت از %s</string>
<string name="room_displayname_room_invite">دعوت اتاق</string>

View file

@ -70,13 +70,6 @@
<string name="summary_user_sent_sticker">%1$s lähetti tarran.</string>
<string name="message_reply_to_prefix">Vastauksena käyttäjälle</string>
<string name="reply_to_an_image">oli lähettänyt kuvan.</string>
<string name="reply_to_a_video">lähetti videon.</string>
<string name="reply_to_an_audio_file">lähetti äänitiedoston.</string>
<string name="reply_to_a_file">lähetti tiedoston.</string>
<plurals name="room_displayname_three_and_more_members">
<item quantity="one">%1$s ja yksi muu</item>
<item quantity="other">%1$s ja %2$d muuta</item>

View file

@ -63,13 +63,6 @@
<string name="summary_user_sent_sticker">%1$s a envoyé un sticker.</string>
<string name="message_reply_to_prefix">En réponse à</string>
<string name="reply_to_an_image">a envoyé une image.</string>
<string name="reply_to_a_video">a envoyé une vidéo.</string>
<string name="reply_to_an_audio_file">a envoyé un fichier audio.</string>
<string name="reply_to_a_file">a envoyé un fichier.</string>
<string name="room_displayname_invite_from">Invitation de %s</string>
<string name="room_displayname_room_invite">Invitation au salon</string>
<string name="room_displayname_empty_room">Salon vide</string>

View file

@ -50,8 +50,6 @@
<string name="notice_crypto_unable_to_decrypt">** Imposíbel descifrar: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">O dispositivo do que envía non enviou as chaves desta mensaxe.</string>
<string name="message_reply_to_prefix">Respondéndolle a</string>
<string name="could_not_redact">Non se puido redactar</string>
<string name="unable_to_send_message">Non foi posíbel enviar a mensaxe</string>
@ -64,11 +62,6 @@
<string name="medium_phone_number">Número de teléfono</string>
<string name="reply_to_an_image">Responder a</string>
<string name="reply_to_a_video">enviar un vídeo.</string>
<string name="reply_to_an_audio_file">enviar un ficheiro de son.</string>
<string name="reply_to_a_file">enviar un ficheiro.</string>
<string name="room_displayname_two_members">%1$s e %2$s</string>

View file

@ -62,13 +62,6 @@
<string name="summary_user_sent_sticker">%1$s küldött egy matricát.</string>
<string name="message_reply_to_prefix">Válasz erre:</string>
<string name="reply_to_an_image">képet küldött.</string>
<string name="reply_to_a_video">videót küldött.</string>
<string name="reply_to_an_audio_file">hangfájlt küldött.</string>
<string name="reply_to_a_file">fájlt küldött.</string>
<string name="room_displayname_invite_from">Meghívó tőle: %s</string>
<string name="room_displayname_room_invite">Meghívó egy szobába</string>
<string name="room_displayname_two_members">%1$s és %2$s</string>

View file

@ -24,7 +24,6 @@
<string name="notice_avatar_changed_too">(einnig var skipt um auðkennismynd)</string>
<string name="notice_crypto_unable_to_decrypt">** Mistókst að afkóða: %s **</string>
<string name="message_reply_to_prefix">Sem svar til</string>
<string name="unable_to_send_message">Gat ekki sent skilaboð</string>

View file

@ -62,13 +62,6 @@
<string name="summary_user_sent_sticker">%1$s ha inviato un adesivo.</string>
<string name="message_reply_to_prefix">In risposta a</string>
<string name="reply_to_an_image">inviata un\'immagine.</string>
<string name="reply_to_a_video">inviato un video.</string>
<string name="reply_to_an_audio_file">inviato un file audio.</string>
<string name="reply_to_a_file">inviato un file.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Invito da %s</string>
<string name="room_displayname_room_invite">Invito nella stanza</string>

View file

@ -56,8 +56,6 @@
<string name="notice_crypto_unable_to_decrypt">** 解読できません: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">送信者の端末からこのメッセージのキーが送信されていません。</string>
<string name="message_reply_to_prefix">に返信</string>
<string name="could_not_redact">修正できませんでした</string>
<string name="unable_to_send_message">メッセージを送信できません</string>
@ -73,9 +71,4 @@
<string name="medium_email">メールアドレス</string>
<string name="medium_phone_number">電話番号</string>
<string name="reply_to_an_image">画像を送信しました。</string>
<string name="reply_to_a_video">動画を送りました。</string>
<string name="reply_to_an_audio_file">音声ファイルを送信しました。</string>
<string name="reply_to_a_file">ファイルを送信しました。</string>
</resources>

View file

@ -52,8 +52,6 @@
<string name="notice_crypto_unable_to_decrypt">** 암호를 복호화할 수 없음: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">발신인의 기기에서 이 메시지의 키를 보내지 않았습니다.</string>
<string name="message_reply_to_prefix">관련 대화</string>
<string name="could_not_redact">검열할 수 없습니다</string>
<string name="unable_to_send_message">메시지를 보낼 수 없습니다</string>
@ -69,11 +67,6 @@
<string name="medium_email">이메일 주소</string>
<string name="medium_phone_number">전화번호</string>
<string name="reply_to_an_image">사진을 보냈습니다.</string>
<string name="reply_to_a_video">동영상을 보냈습니다.</string>
<string name="reply_to_an_audio_file">오디오 파일을 보냈습니다.</string>
<string name="reply_to_a_file">파일을 보냈습니다.</string>
<string name="room_displayname_invite_from">%s에서 초대함</string>
<string name="room_displayname_room_invite">방 초대</string>

View file

@ -71,13 +71,6 @@
<string name="summary_user_sent_sticker">%1$s heeft een sticker gestuurd.</string>
<string name="message_reply_to_prefix">Als antwoord op</string>
<string name="reply_to_an_image">heeft een afbeelding gestuurd.</string>
<string name="reply_to_a_video">heeft een video gestuurd.</string>
<string name="reply_to_an_audio_file">heeft een audiobestand gestuurd.</string>
<string name="reply_to_a_file">heeft een bestand gestuurd.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Uitnodiging van %s</string>
<string name="room_displayname_room_invite">Gespreksuitnodiging</string>

View file

@ -49,8 +49,6 @@
<string name="notice_crypto_unable_to_decrypt">** Fekk ikkje til å dekryptera: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Avsendareiningi hev ikkje sendt oss nyklane fyr denna meldingi.</string>
<string name="message_reply_to_prefix">Som svar til</string>
<string name="could_not_redact">Kunde ikkje gjera um</string>
<string name="unable_to_send_message">Fekk ikkje å senda meldingi</string>
@ -64,11 +62,6 @@
<string name="medium_email">Epostadresse</string>
<string name="medium_phone_number">Telefonnummer</string>
<string name="reply_to_an_image">sende eit bilæte.</string>
<string name="reply_to_a_video">sende ein video.</string>
<string name="reply_to_an_audio_file">sende ei ljodfil.</string>
<string name="reply_to_a_file">sende ei fil.</string>
<string name="room_displayname_invite_from">Innbjoding frå %s</string>
<string name="room_displayname_room_invite">Rominnbjoding</string>
<string name="room_displayname_two_members">%1$s og %2$s</string>

View file

@ -42,7 +42,6 @@
<string name="notice_room_withdraw">%1$s wycofał(a) zaproszenie %2$s</string>
<string name="notice_answered_call">%s odebrał(a) połączenie.</string>
<string name="notice_avatar_changed_too">(awatar też został zmieniony)</string>
<string name="message_reply_to_prefix">W odpowiedzi do</string>
<string name="room_displayname_invite_from">Zaproszenie od %s</string>
<string name="room_displayname_room_invite">Zaproszenie do pokoju</string>
@ -76,11 +75,6 @@
<string name="could_not_redact">Nie można zredagować</string>
<string name="room_error_join_failed_empty_room">Obecnie nie jest możliwe ponowne dołączenie do pustego pokoju.</string>
<string name="reply_to_an_image">wyślij zdjęcie.</string>
<string name="reply_to_a_video">wyślij wideo.</string>
<string name="reply_to_an_audio_file">wyślij plik audio.</string>
<string name="reply_to_a_file">wyślij plik.</string>
<string name="notice_event_redacted">Wiadomość usunięta</string>
<string name="notice_event_redacted_by">Wiadomość usunięta przez %1$s</string>
<string name="notice_event_redacted_with_reason">Wiadomość usunięta [powód: %1$s]</string>

View file

@ -74,13 +74,6 @@
<string name="summary_user_sent_sticker">%1$s enviou um sticker.</string>
<string name="message_reply_to_prefix">Em resposta a</string>
<string name="reply_to_an_image">enviou uma imagem.</string>
<string name="reply_to_a_video">enviou um vídeo.</string>
<string name="reply_to_an_audio_file">enviou um arquivo de áudio.</string>
<string name="reply_to_a_file">enviou um arquivo.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Convite de %s</string>
<string name="room_displayname_room_invite">Convite para sala</string>

View file

@ -73,13 +73,6 @@
<string name="summary_user_sent_sticker">%1$s отправил стикер.</string>
<string name="message_reply_to_prefix">В ответ на</string>
<string name="reply_to_an_image">отправил изображение.</string>
<string name="reply_to_a_video">отправил видео.</string>
<string name="reply_to_an_audio_file">отправил аудиофайл.</string>
<string name="reply_to_a_file">отправил файл.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Приглашение от %s</string>
<string name="room_displayname_room_invite">Приглашение в комнату</string>

View file

@ -62,13 +62,6 @@
<string name="summary_user_sent_sticker">%1$s poslal nálepku.</string>
<string name="message_reply_to_prefix">Odpoveď na</string>
<string name="reply_to_an_image">odoslal obrázok.</string>
<string name="reply_to_a_video">odoslal video.</string>
<string name="reply_to_an_audio_file">odoslal zvukový súbor.</string>
<string name="reply_to_a_file">Odoslal súbor.</string>
<string name="room_displayname_invite_from">Pozvanie od %s</string>
<string name="room_displayname_room_invite">Pozvanie do miestnosti</string>
<string name="room_displayname_two_members">%1$s a %2$s</string>

View file

@ -34,8 +34,6 @@
<string name="notice_crypto_unable_to_decrypt">** Sarrihet të shfshehtëzohet: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Pajisja e dërguesit nuk na ka dërguar kyçet për këtë mesazh.</string>
<string name="message_reply_to_prefix">Në përgjigje të</string>
<string name="could_not_redact">Su redaktua dot</string>
<string name="unable_to_send_message">Sarrihet të dërgohet mesazh</string>
@ -51,11 +49,6 @@
<string name="medium_email">Adresë email</string>
<string name="medium_phone_number">Numër telefoni</string>
<string name="reply_to_an_image">dërgoi një figurë.</string>
<string name="reply_to_a_video">dërgoi një video.</string>
<string name="reply_to_an_audio_file">dërgoi një kartelë audio.</string>
<string name="reply_to_a_file">dërgoi një kartelë.</string>
<string name="room_displayname_invite_from">Ftesë nga %s</string>
<string name="room_displayname_room_invite">Ftesë Dhome</string>

View file

@ -56,8 +56,6 @@
<string name="notice_crypto_unable_to_decrypt">** Неможливо розшифрувати: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">Пристрій відправника не надіслав нам ключ для цього повідомлення.</string>
<string name="message_reply_to_prefix">У відповідь на</string>
<string name="could_not_redact">Неможливо відредагувати</string>
<string name="unable_to_send_message">Не вдалося надіслати повідомлення</string>
@ -71,11 +69,6 @@
<string name="medium_email">Адреса електронної пошти</string>
<string name="medium_phone_number">Номер телефону</string>
<string name="reply_to_an_image">надіслав зображення.</string>
<string name="reply_to_a_video">надіслав відео.</string>
<string name="reply_to_an_audio_file">надіслав аудіо файл.</string>
<string name="reply_to_a_file">надіслав файл.</string>
<plurals name="room_displayname_three_and_more_members">
<item quantity="one">%1$s та 1 інший</item>
<item quantity="few">%1$s та %2$d інші</item>

View file

@ -50,8 +50,6 @@
<string name="notice_crypto_unable_to_decrypt">** Kun nie ountsleuteln: %s **</string>
<string name="notice_crypto_error_unkwown_inbound_session_id">t Toestel van den afzender èt geen sleutels vo da bericht hier gesteurd.</string>
<string name="message_reply_to_prefix">Als antwoord ip</string>
<string name="could_not_redact">Kosteg nie verwyderd wordn</string>
<string name="unable_to_send_message">Kosteg t bericht nie verzendn</string>
@ -67,11 +65,6 @@
<string name="medium_email">E-mailadresse</string>
<string name="medium_phone_number">Telefongnumero</string>
<string name="reply_to_an_image">èt e fotootje gesteurd.</string>
<string name="reply_to_a_video">èt e filmtje gesteurd.</string>
<string name="reply_to_an_audio_file">èt e geluudsfragment gesteurd.</string>
<string name="reply_to_a_file">èt e bestand gesteurd.</string>
<string name="room_displayname_invite_from">Uutnodigienge van %s</string>
<string name="room_displayname_room_invite">Gespreksuutnodigienge</string>

View file

@ -63,13 +63,6 @@
<string name="summary_message">%1$s%2$s</string>
<string name="summary_user_sent_sticker">%1$s 发送了一张贴纸。</string>
<string name="reply_to_an_image">发送了一张图片。</string>
<string name="reply_to_a_video">发送了一个视频。</string>
<string name="reply_to_an_audio_file">发送了一段音频。</string>
<string name="reply_to_a_file">发送了一个文件。</string>
<string name="message_reply_to_prefix">回复</string>
<string name="room_displayname_empty_room">空聊天室</string>
<string name="room_displayname_invite_from">来自 %s 的邀请</string>
<string name="room_displayname_room_invite">聊天室邀请</string>

View file

@ -62,13 +62,6 @@
<string name="summary_user_sent_sticker">%1$s 傳送了一張貼圖。</string>
<string name="message_reply_to_prefix">回覆</string>
<string name="reply_to_an_image">傳送了圖片。</string>
<string name="reply_to_a_video">傳送了影片。</string>
<string name="reply_to_an_audio_file">傳送了音訊檔案。</string>
<string name="reply_to_a_file">傳送了檔案。</string>
<string name="room_displayname_invite_from">來自%s 的邀請</string>
<string name="room_displayname_room_invite">聊天室邀請</string>
<string name="room_displayname_two_members">%1$s 和 %2$s</string>

View file

@ -112,7 +112,6 @@
<string name="notice_crypto_error_unkwown_inbound_session_id">The sender\'s device has not sent us the keys for this message.</string>
<!-- Messages -->
<string name="message_reply_to_prefix">In reply to</string>
<!-- Room Screen -->
<string name="could_not_redact">Could not redact</string>
@ -139,12 +138,6 @@
<string name="medium_email">Email address</string>
<string name="medium_phone_number">Phone number</string>
<!-- Reply to -->
<string name="reply_to_an_image">sent an image.</string>
<string name="reply_to_a_video">sent a video.</string>
<string name="reply_to_an_audio_file">sent an audio file.</string>
<string name="reply_to_a_file">sent a file.</string>
<!-- Room display name -->
<string name="room_displayname_invite_from">Invite from %s</string>
<string name="room_displayname_room_invite">Room Invite</string>

View file

@ -106,6 +106,11 @@ def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0
android {
compileSdkVersion 29
// Due to a bug introduced in Android gradle plugin 3.6.0, we have to specify the ndk version to use
// Ref: https://issuetracker.google.com/issues/144111441
ndkVersion "21.3.6528147"
defaultConfig {
applicationId "im.vector.app"
// Set to API 21: see #405
@ -232,8 +237,7 @@ android {
lintOptions {
lintConfig file("lint.xml")
// TODO Restore true once pb with WorkManager is fixed
abortOnError false
abortOnError true
}
compileOptions {

View file

@ -247,6 +247,12 @@
<!-- Providers -->
<!-- Remove WorkManagerInitializer Provider because we are using on-demand initialization of WorkManager-->
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"

View file

@ -63,7 +63,13 @@ import java.util.Locale
import java.util.concurrent.Executors
import javax.inject.Inject
class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
import androidx.work.Configuration as WorkConfiguration
class VectorApplication :
Application(),
HasVectorInjector,
MatrixConfiguration.Provider,
WorkConfiguration.Provider {
lateinit var appContext: Context
@Inject lateinit var legacySessionImporter: LegacySessionImporter
@ -85,6 +91,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
@Inject lateinit var webRtcPeerConnectionManager: WebRtcPeerConnectionManager
lateinit var vectorComponent: VectorComponent
// font thread handler
private var fontThreadHandler: Handler? = null
@ -157,7 +164,11 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
override fun providesMatrixConfiguration() = MatrixConfiguration(BuildConfig.FLAVOR_DESCRIPTION)
override fun getWorkManagerConfiguration() = androidx.work.Configuration.Builder().setExecutor(Executors.newCachedThreadPool()).build()
override fun getWorkManagerConfiguration(): WorkConfiguration {
return WorkConfiguration.Builder()
.setExecutor(Executors.newCachedThreadPool())
.build()
}
override fun injector(): VectorComponent {
return vectorComponent

View file

@ -17,29 +17,39 @@
package im.vector.riotx.core.utils
import android.app.Activity
import android.app.DownloadManager
import android.content.ActivityNotFoundException
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Browser
import android.provider.MediaStore
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsSession
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
import im.vector.matrix.android.api.extensions.tryThis
import im.vector.riotx.BuildConfig
import im.vector.riotx.R
import im.vector.riotx.features.notifications.NotificationUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okio.buffer
import okio.sink
import okio.source
import timber.log.Timber
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@ -301,42 +311,20 @@ fun shareMedia(context: Context, file: File, mediaMimeType: String?) {
fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String?, notificationUtils: NotificationUtils) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val externalContentUri: Uri
val values = ContentValues()
when {
mediaMimeType?.startsWith("image/") == true -> {
externalContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
values.put(MediaStore.Images.Media.TITLE, title)
values.put(MediaStore.Images.Media.DISPLAY_NAME, title)
values.put(MediaStore.Images.Media.MIME_TYPE, mediaMimeType)
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
}
mediaMimeType?.startsWith("video/") == true -> {
externalContentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
values.put(MediaStore.Video.Media.TITLE, title)
values.put(MediaStore.Video.Media.DISPLAY_NAME, title)
values.put(MediaStore.Video.Media.MIME_TYPE, mediaMimeType)
values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis())
}
mediaMimeType?.startsWith("audio/") == true -> {
externalContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
values.put(MediaStore.Audio.Media.TITLE, title)
values.put(MediaStore.Audio.Media.DISPLAY_NAME, title)
values.put(MediaStore.Audio.Media.MIME_TYPE, mediaMimeType)
values.put(MediaStore.Audio.Media.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.Audio.Media.DATE_TAKEN, System.currentTimeMillis())
}
else -> {
externalContentUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI
values.put(MediaStore.Downloads.TITLE, title)
values.put(MediaStore.Downloads.DISPLAY_NAME, title)
values.put(MediaStore.Downloads.MIME_TYPE, mediaMimeType)
values.put(MediaStore.Downloads.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.Downloads.DATE_TAKEN, System.currentTimeMillis())
}
val values = ContentValues().apply {
put(MediaStore.Images.Media.TITLE, title)
put(MediaStore.Images.Media.DISPLAY_NAME, title)
put(MediaStore.Images.Media.MIME_TYPE, mediaMimeType)
put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
}
val externalContentUri = when {
mediaMimeType?.startsWith("image/") == true -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
mediaMimeType?.startsWith("video/") == true -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
mediaMimeType?.startsWith("audio/") == true -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
else -> MediaStore.Downloads.EXTERNAL_CONTENT_URI
}
val uri = context.contentResolver.insert(externalContentUri, values)
if (uri == null) {
Toast.makeText(context, R.string.error_saving_media_file, Toast.LENGTH_LONG).show()
@ -357,16 +345,70 @@ fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String
notificationUtils.showNotificationMessage("DL", uri.hashCode(), notification)
}
}
// TODO add notification?
} else {
@Suppress("DEPRECATION")
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
mediaScanIntent.data = Uri.fromFile(file)
context.sendBroadcast(mediaScanIntent)
saveMediaLegacy(context, mediaMimeType, title, file)
}
}
@Suppress("DEPRECATION")
private fun saveMediaLegacy(context: Context, mediaMimeType: String?, title: String, file: File) {
val state = Environment.getExternalStorageState()
if (Environment.MEDIA_MOUNTED != state) {
context.toast(context.getString(R.string.error_saving_media_file))
return
}
GlobalScope.launch(Dispatchers.IO) {
val dest = when {
mediaMimeType?.startsWith("image/") == true -> Environment.DIRECTORY_PICTURES
mediaMimeType?.startsWith("video/") == true -> Environment.DIRECTORY_MOVIES
mediaMimeType?.startsWith("audio/") == true -> Environment.DIRECTORY_MUSIC
else -> Environment.DIRECTORY_DOWNLOADS
}
val downloadDir = Environment.getExternalStoragePublicDirectory(dest)
try {
val outputFilename = if (title.substringAfterLast('.', "").isEmpty()) {
val extension = mediaMimeType?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) }
"$title.$extension"
} else {
title
}
val savedFile = saveFileIntoLegacy(file, downloadDir, outputFilename)
if (savedFile != null) {
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as? DownloadManager
downloadManager?.addCompletedDownload(
savedFile.name,
title,
true,
mediaMimeType ?: "application/octet-stream",
savedFile.absolutePath,
savedFile.length(),
true)
addToGallery(savedFile, mediaMimeType, context)
}
} catch (error: Throwable) {
GlobalScope.launch(Dispatchers.Main) {
context.toast(context.getString(R.string.error_saving_media_file))
}
}
}
}
private fun addToGallery(savedFile: File, mediaMimeType: String?, context: Context) {
// MediaScannerConnection provides a way for applications to pass a newly created or downloaded media file to the media scanner service.
var mediaConnection: MediaScannerConnection? = null
val mediaScannerConnectionClient: MediaScannerConnection.MediaScannerConnectionClient = object : MediaScannerConnection.MediaScannerConnectionClient {
override fun onMediaScannerConnected() {
mediaConnection?.scanFile(savedFile.path, mediaMimeType)
}
override fun onScanCompleted(path: String, uri: Uri?) {
if (path == savedFile.path) mediaConnection?.disconnect()
}
}
mediaConnection = MediaScannerConnection(context, mediaScannerConnectionClient).apply { connect() }
}
/**
* Open the play store to the provided application Id, default to this app
*/
@ -381,3 +423,76 @@ fun openPlayStore(activity: Activity, appId: String = BuildConfig.APPLICATION_ID
}
}
}
// ==============================================================================================================
// Media utils
// ==============================================================================================================
/**
* Copy a file into a dstPath directory.
* The output filename can be provided.
* The output file is not overridden if it is already exist.
*
* ~~ This is copied from the old matrix sdk ~~
*
* @param sourceFile the file source path
* @param dstDirPath the dst path
* @param outputFilename optional the output filename
* @param callback the asynchronous callback
*/
@Suppress("DEPRECATION")
fun saveFileIntoLegacy(sourceFile: File, dstDirPath: File, outputFilename: String?): File? {
// defines another name for the external media
val dstFileName: String
// build a filename is not provided
if (null == outputFilename) {
// extract the file extension from the uri
val dotPos = sourceFile.name.lastIndexOf(".")
var fileExt = ""
if (dotPos > 0) {
fileExt = sourceFile.name.substring(dotPos)
}
dstFileName = "vector_" + System.currentTimeMillis() + fileExt
} else {
dstFileName = outputFilename
}
var dstFile = File(dstDirPath, dstFileName)
// if the file already exists, append a marker
if (dstFile.exists()) {
var baseFileName = dstFileName
var fileExt = ""
val lastDotPos = dstFileName.lastIndexOf(".")
if (lastDotPos > 0) {
baseFileName = dstFileName.substring(0, lastDotPos)
fileExt = dstFileName.substring(lastDotPos)
}
var counter = 1
while (dstFile.exists()) {
dstFile = File(dstDirPath, "$baseFileName($counter)$fileExt")
counter++
}
}
// Copy source file to destination
var inputStream: FileInputStream? = null
var outputStream: FileOutputStream? = null
try {
dstFile.createNewFile()
inputStream = FileInputStream(sourceFile)
outputStream = FileOutputStream(dstFile)
val buffer = ByteArray(1024 * 10)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {
outputStream.write(buffer, 0, len)
}
return dstFile
} catch (failure: Throwable) {
return null
} finally {
// Close resources
tryThis { inputStream?.close() }
tryThis { outputStream?.close() }
}
}

View file

@ -56,6 +56,7 @@ abstract class FormEditTextWithButtonItem : VectorEpoxyModel<FormEditTextWithBut
}
override fun bind(holder: Holder) {
super.bind(holder)
holder.textInputLayout.isEnabled = enabled
holder.textInputLayout.hint = hint

View file

@ -22,6 +22,7 @@ import android.content.DialogInterface
import android.content.Intent
import android.graphics.Typeface
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.text.Spannable
@ -222,6 +223,7 @@ class RoomDetailFragment @Inject constructor(
private const val AUDIO_CALL_PERMISSION_REQUEST_CODE = 1
private const val VIDEO_CALL_PERMISSION_REQUEST_CODE = 2
private const val SAVE_ATTACHEMENT_REQUEST_CODE = 3
/**
* Sanitize the display name.
@ -1194,17 +1196,12 @@ class RoomDetailFragment @Inject constructor(
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if (allGranted(grantResults)) {
when (requestCode) {
// PERMISSION_REQUEST_CODE_DOWNLOAD_FILE -> {
// val action = roomDetailViewModel.pendingAction
// if (action != null) {
// (action as? RoomDetailAction.DownloadFile)
// ?.messageFileContent
// ?.getFileName()
// ?.let { showSnackWithMessage(getString(R.string.downloading_file, it)) }
// roomDetailViewModel.pendingAction = null
// roomDetailViewModel.handle(action)
// }
// }
SAVE_ATTACHEMENT_REQUEST_CODE -> {
sharedActionViewModel.pendingAction?.let {
handleActions(it)
sharedActionViewModel.pendingAction = null
}
}
PERMISSION_REQUEST_CODE_INCOMING_URI -> {
val pendingUri = roomDetailViewModel.pendingUri
if (pendingUri != null) {
@ -1357,6 +1354,11 @@ class RoomDetailFragment @Inject constructor(
}
private fun onSaveActionClicked(action: EventSharedAction.Save) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
&& !checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, SAVE_ATTACHEMENT_REQUEST_CODE)) {
sharedActionViewModel.pendingAction = action
return
}
session.fileService().downloadFile(
downloadMode = FileService.DownloadMode.FOR_EXTERNAL_SHARE,
id = action.eventId,

View file

@ -21,4 +21,6 @@ import javax.inject.Inject
/**
* Activity shared view model to handle message actions
*/
class MessageSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel<EventSharedAction>()
class MessageSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel<EventSharedAction>() {
var pendingAction : EventSharedAction? = null
}