Merge branch 'develop' into feature/switch_language

This commit is contained in:
Benoit Marty 2020-08-26 17:34:17 +02:00 committed by GitHub
commit 7ef08579ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 96 additions and 87 deletions

View file

@ -5,12 +5,14 @@ Features ✨:
-
Improvements 🙌:
-
- Add long click gesture to copy userId, user display name, room name, room topic and room alias (#1774)
Bugfix 🐛:
- Display name not shown under Settings/General (#1926)
- Fix changing language issue
- Fix FontSize issue (#1483, #1787)
- Fix bad color for settings icon on Android < 24 (#1786)
- Change user or room avatar: when selecting Gallery, I'm not proposed to crop the selected image (#1590)
Translations 🗣:
-
@ -22,7 +24,7 @@ Build 🧱:
- Some dependencies have been upgraded (coroutine, recyclerView, appCompat, core-ktx, firebase-messaging)
Other changes:
-
- Use File extension functions to make code more concise (#1996)
Changes in Element 1.0.5 (2020-08-21)
===================================================

View file

@ -29,7 +29,6 @@ import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import java.io.ByteArrayInputStream
import java.io.InputStream
/**
@ -46,7 +45,7 @@ class AttachmentEncryptionTest {
val inputStream: InputStream
inputStream = if (`in`.isEmpty()) {
ByteArrayInputStream(`in`)
`in`.inputStream()
} else {
val memoryFile = MemoryFile("file" + System.currentTimeMillis(), `in`.size)
memoryFile.outputStream.write(`in`)

View file

@ -21,7 +21,6 @@ import android.util.Base64
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.security.MessageDigest
@ -179,7 +178,7 @@ internal object MXEncryptedAttachments {
return null
}
return ByteArrayInputStream(outputStream.toByteArray())
return outputStream.toByteArray().inputStream()
.also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") }
} catch (oom: OutOfMemoryError) {
Timber.e(oom, "## decryptAttachment() failed: OOM")

View file

@ -21,7 +21,6 @@ import android.util.Base64
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmObject
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.util.zip.GZIPInputStream
@ -96,7 +95,7 @@ fun <T> deserializeFromRealm(string: String?): T? {
}
val decodedB64 = Base64.decode(string.toByteArray(), Base64.DEFAULT)
val bais = ByteArrayInputStream(decodedB64)
val bais = decodedB64.inputStream()
val gzis = GZIPInputStream(bais)
val ois = SafeObjectInputStream(gzis)
return ois.use {

View file

@ -42,10 +42,7 @@ import org.matrix.android.sdk.internal.worker.SessionWorkerParams
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
import org.matrix.android.sdk.internal.worker.getSessionComponent
import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.UUID
import javax.inject.Inject
@ -130,7 +127,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
val contentUploadResponse = if (params.isEncrypted) {
Timber.v("Encrypt thumbnail")
notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) }
val encryptionResult = MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream(), thumbnailData.mimeType)
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
"thumb_${attachment.name}",
@ -176,7 +173,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
cacheFile.createNewFile()
cacheFile.deleteOnExit()
val outputStream = FileOutputStream(cacheFile)
val outputStream = cacheFile.outputStream()
outputStream.use {
inputStream.copyTo(outputStream)
}
@ -203,7 +200,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
Timber.v("Encrypt file")
notifyTracker(params) { contentUploadStateTracker.setEncrypting(it) }
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(cacheFile), attachment.getSafeMimeType())
val encryptionResult = MXEncryptedAttachments.encryptAttachment(cacheFile.inputStream(), attachment.getSafeMimeType())
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
fileUploader

View file

@ -219,7 +219,7 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
@RequiresApi(Build.VERSION_CODES.M)
private fun decryptStringM(encryptedChunk: ByteArray, keyAlias: String): String {
val (iv, encryptedText) = formatMExtract(ByteArrayInputStream(encryptedChunk))
val (iv, encryptedText) = formatMExtract(encryptedChunk.inputStream())
val secretKey = getOrGenerateSymmetricKeyForAliasM(keyAlias)

View file

@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.util
import androidx.annotation.WorkerThread
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
/**
@ -27,7 +26,7 @@ import java.io.InputStream
*/
@WorkerThread
fun writeToFile(inputStream: InputStream, outputFile: File) {
FileOutputStream(outputFile).use {
outputFile.outputStream().use {
inputStream.copyTo(it)
}
}

View file

@ -378,7 +378,7 @@ dependencies {
implementation "com.github.bumptech.glide:glide:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"
implementation 'com.danikula:videocache:2.7.1'
implementation 'com.github.yalantis:ucrop:2.2.4'
implementation 'com.github.yalantis:ucrop:2.2.6'
// Badge for compatibility
implementation 'me.leolin:ShortcutBadger:1.1.22@aar'

View file

@ -24,7 +24,9 @@ import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.StringRes
import androidx.core.view.isVisible
import com.google.android.material.snackbar.Snackbar
import im.vector.app.R
import im.vector.app.core.utils.copyToClipboard
import im.vector.app.features.themes.ThemeUtils
/**
@ -68,3 +70,18 @@ fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
}
}
}
/**
* Set long click listener to copy the current text of the TextView to the clipboard and show a Snackbar
*/
fun TextView.copyOnLongClick() {
setOnLongClickListener { view ->
(view as? TextView)
?.text
?.let { text ->
copyToClipboard(view.context, text, false)
Snackbar.make(view, view.resources.getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT).show()
}
true
}
}

View file

@ -31,7 +31,6 @@ import okhttp3.OkHttpClient
import okhttp3.Request
import timber.log.Timber
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
@ -97,7 +96,7 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde
Timber.v("Load data: $data")
if (data.isLocalFile() && data.url != null) {
val initialFile = File(data.url)
callback.onDataReady(FileInputStream(initialFile))
callback.onDataReady(initialFile.inputStream())
return
}
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()

View file

@ -20,7 +20,6 @@ import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.RadioGroup
import android.widget.TextView
import androidx.preference.PreferenceViewHolder
import im.vector.app.R
import org.matrix.android.sdk.api.pushrules.RuleSetKey
@ -162,7 +161,7 @@ class PushRulePreference : VectorPreference {
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
holder.itemView.findViewById<TextView>(android.R.id.summary)?.visibility = View.GONE
holder.findViewById(android.R.id.summary)?.visibility = View.GONE
holder.itemView.setOnClickListener(null)
holder.itemView.setOnLongClickListener(null)

View file

@ -45,7 +45,7 @@ class VectorEditTextPreference : EditTextPreference {
override fun onBindViewHolder(holder: PreferenceViewHolder) {
// display the title in multi-line to avoid ellipsis.
try {
holder.itemView.findViewById<TextView>(android.R.id.title)?.isSingleLine = false
(holder.findViewById(android.R.id.title) as? TextView)?.isSingleLine = false
} catch (e: Exception) {
Timber.e(e, "onBindView")
}

View file

@ -20,12 +20,15 @@ import android.animation.Animator
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Typeface
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.core.animation.doOnEnd
import androidx.core.widget.ImageViewCompat
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import im.vector.app.R
@ -76,6 +79,12 @@ open class VectorPreference : Preference {
notifyChanged()
}
var tintIcon = false
set(value) {
field = value
notifyChanged()
}
var currentHighlightAnimator: Animator? = null
override fun onBindViewHolder(holder: PreferenceViewHolder) {
@ -84,15 +93,23 @@ open class VectorPreference : Preference {
// display the title in multi-line to avoid ellipsis.
try {
val title = itemView.findViewById<TextView>(android.R.id.title)
val summary = itemView.findViewById<TextView>(android.R.id.summary)
val title = holder.findViewById(android.R.id.title) as? TextView
val summary = holder.findViewById(android.R.id.summary) as? TextView
if (title != null) {
title.isSingleLine = false
title.setTypeface(null, mTypeface)
}
if (title !== summary) {
summary.setTypeface(null, mTypeface)
summary?.setTypeface(null, mTypeface)
if (tintIcon) {
// Tint icons (See #1786)
val icon = holder.findViewById(android.R.id.icon) as? ImageView
icon?.let {
val color = ThemeUtils.getColor(context, R.attr.riotx_header_panel_text_secondary)
ImageViewCompat.setImageTintList(it, ColorStateList.valueOf(color))
}
}
// cancel existing animation (find a way to resume if happens during anim?)

View file

@ -45,7 +45,7 @@ class VectorPreferenceCategory : PreferenceCategory {
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val titleTextView = holder.itemView.findViewById<TextView>(android.R.id.title)
val titleTextView = holder.findViewById(android.R.id.title) as? TextView
titleTextView?.setTypeface(null, Typeface.BOLD)
titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_primary))

View file

@ -58,7 +58,7 @@ class VectorSwitchPreference : SwitchPreference {
override fun onBindViewHolder(holder: PreferenceViewHolder) {
// display the title in multi-line to avoid ellipsis.
holder.itemView.findViewById<TextView>(android.R.id.title)?.isSingleLine = false
(holder.findViewById(android.R.id.title) as? TextView)?.isSingleLine = false
// cancel existing animation (find a way to resume if happens during anim?)
currentHighlightAnimator?.cancel()

View file

@ -518,8 +518,8 @@ fun saveFileIntoLegacy(sourceFile: File, dstDirPath: File, outputFilename: Strin
var outputStream: FileOutputStream? = null
try {
dstFile.createNewFile()
inputStream = FileInputStream(sourceFile)
outputStream = FileOutputStream(dstFile)
inputStream = sourceFile.inputStream()
outputStream = dstFile.outputStream()
val buffer = ByteArray(1024 * 10)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {

View file

@ -144,9 +144,7 @@ class BigImageViewerActivity : VectorBaseActivity() {
.get(MultiPicker.IMAGE)
.getSelectedFiles(this, requestCode, resultCode, data)
.firstOrNull()?.let {
// TODO. UCrop library cannot read from Gallery. For now, we will set avatar as it is.
// onRoomAvatarSelected(it)
onAvatarCropped(it.contentUri)
onRoomAvatarSelected(it)
}
}
UCrop.REQUEST_CROP -> data?.let { onAvatarCropped(UCrop.getOutput(it)) }

View file

@ -32,7 +32,6 @@ import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import me.gujun.android.span.span
import timber.log.Timber
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import javax.inject.Inject
import javax.inject.Singleton
@ -494,7 +493,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
try {
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) {
FileInputStream(file).use {
file.inputStream().use {
val events: ArrayList<NotifiableEvent>? = currentSession?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE)
if (events != null) {
return events.toMutableList()

View file

@ -35,6 +35,7 @@ import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener
import im.vector.app.core.dialogs.ConfirmationDialogBuilder
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.copyOnLongClick
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.StateView
@ -44,11 +45,11 @@ import im.vector.app.features.crypto.verification.VerificationBottomSheet
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
import org.matrix.android.sdk.api.session.room.powerlevels.Role
import org.matrix.android.sdk.api.util.MatrixItem
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_matrix_profile.*
import kotlinx.android.synthetic.main.view_stub_room_member_profile_header.*
import org.matrix.android.sdk.api.session.room.powerlevels.Role
import org.matrix.android.sdk.api.util.MatrixItem
import javax.inject.Inject
@Parcelize
@ -110,6 +111,12 @@ class RoomMemberProfileFragment @Inject constructor(
is RoomMemberProfileViewEvents.OnInviteActionSuccess -> Unit
}.exhaustive
}
setupLongClicks()
}
private fun setupLongClicks() {
memberProfileNameView.copyOnLongClick()
memberProfileIdView.copyOnLongClick()
}
private fun handleShowPowerLevelDemoteWarning(event: RoomMemberProfileViewEvents.ShowPowerLevelDemoteWarning) {

View file

@ -34,16 +34,12 @@ import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.yalantis.ucrop.UCrop
import im.vector.lib.multipicker.MultiPicker
import im.vector.lib.multipicker.entity.MultiPickerImageType
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
import im.vector.app.R
import im.vector.app.core.animations.AppBarStateChangeListener
import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.copyOnLongClick
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.intent.getFilenameFromUri
@ -62,9 +58,14 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
import im.vector.app.features.media.BigImageViewerActivity
import im.vector.app.features.media.createUCropWithDefaultSettings
import im.vector.lib.multipicker.MultiPicker
import im.vector.lib.multipicker.entity.MultiPickerImageType
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_matrix_profile.*
import kotlinx.android.synthetic.main.view_stub_room_profile_header.*
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
import timber.log.Timber
import java.io.File
import javax.inject.Inject
@ -120,6 +121,13 @@ class RoomProfileFragment @Inject constructor(
.observe()
.subscribe { handleQuickActions(it) }
.disposeOnDestroyView()
setupLongClicks()
}
private fun setupLongClicks() {
roomProfileNameView.copyOnLongClick()
roomProfileAliasView.copyOnLongClick()
roomProfileTopicView.copyOnLongClick()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -301,9 +309,7 @@ class RoomProfileFragment @Inject constructor(
.get(MultiPicker.IMAGE)
.getSelectedFiles(requireContext(), requestCode, resultCode, data)
.firstOrNull()?.let {
// TODO. UCrop library cannot read from Gallery. For now, we will set avatar as it is.
// onRoomAvatarSelected(it)
onAvatarCropped(it.contentUri)
onRoomAvatarSelected(it)
}
}
UCrop.REQUEST_CROP -> data?.let { onAvatarCropped(UCrop.getOutput(it)) }

View file

@ -356,8 +356,7 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
.get(MultiPicker.IMAGE)
.getSelectedFiles(requireContext(), requestCode, resultCode, data)
.firstOrNull()?.let {
// TODO. UCrop library cannot read from Gallery. For now, we will set avatar as it is.
onAvatarCropped(it.contentUri)
onAvatarSelected(it)
}
}
UCrop.REQUEST_CROP -> data?.let { onAvatarCropped(UCrop.getOutput(it)) }

View file

@ -16,7 +16,9 @@
package im.vector.app.features.settings
import android.os.Build
import im.vector.app.R
import im.vector.app.core.preference.VectorPreference
import javax.inject.Inject
class VectorSettingsRootFragment @Inject constructor() : VectorSettingsBaseFragment() {
@ -25,6 +27,15 @@ class VectorSettingsRootFragment @Inject constructor() : VectorSettingsBaseFragm
override val preferenceXmlRes = R.xml.vector_settings_root
override fun bindPref() {
// Nothing to do
// Tint icon on API < 24
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
tintIcons()
}
}
private fun tintIcons() {
for (i in 0 until preferenceScreen.preferenceCount) {
(preferenceScreen.getPreference(i) as? VectorPreference)?.let { it.tintIcon = true }
}
}
}

View file

@ -1,38 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="163dp"
android:height="127dp"
android:viewportWidth="163"
android:viewportHeight="127">
<path
android:pathData="M113.569,169.348C129.753,185.532 153.161,188.363 165.853,175.671C178.545,162.979 175.715,139.57 159.531,123.386C143.347,107.203 44.653,8.372 44.653,8.372L35.819,18.975C35.819,18.975 39.221,27.764 37.204,30.186C35.186,32.608 24.684,32.34 24.684,32.34L6.34,54.358C6.34,54.358 4.89,60.67 6.106,61.885C41.927,97.706 77.748,133.527 113.569,169.348Z"
android:strokeWidth="1"
android:fillColor="#000000"
android:fillAlpha="0.147508741"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M19.447,19.068L19.447,27.722L28.202,27.713C28.313,27.713 28.415,27.71 28.515,27.703C30.818,27.551 32.617,25.656 32.617,23.391C32.617,21.007 30.641,19.068 28.211,19.068L19.447,19.068ZM10.788,61.81C6.006,61.81 2.129,58.007 2.129,53.316L2.129,37.127C2.097,36.833 2.08,36.535 2.08,36.232C2.08,35.925 2.096,35.621 2.129,35.322L2.129,10.574C2.129,5.882 6.006,2.079 10.788,2.079L28.211,2.079C40.19,2.079 49.935,11.639 49.935,23.391C49.935,34.563 41.04,43.902 29.684,44.652C29.201,44.685 28.704,44.702 28.211,44.702L19.447,44.71L19.447,53.316C19.447,58.007 15.57,61.81 10.788,61.81L10.788,61.81Z"
android:strokeWidth="1"
android:fillColor="#A2DDEF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M19.447,19.068L19.447,27.722L28.202,27.713C28.313,27.713 28.415,27.71 28.515,27.703C30.818,27.551 32.617,25.656 32.617,23.391C32.617,21.007 30.641,19.068 28.211,19.068L19.447,19.068ZM10.788,61.81C6.006,61.81 2.129,58.007 2.129,53.316L2.129,10.574C2.129,5.882 6.006,2.079 10.788,2.079L28.211,2.079C40.19,2.079 49.935,11.639 49.935,23.391C49.935,34.563 41.04,43.902 29.684,44.652C29.201,44.685 28.704,44.702 28.211,44.702L19.447,44.71L19.447,53.316C19.447,58.007 15.57,61.81 10.788,61.81Z"
android:strokeWidth="1.52445396"
android:fillColor="#00000000"
android:strokeColor="#368BD6"
android:fillType="evenOdd"/>
<path
android:pathData="M10.788,53.315L10.788,10.574L28.211,10.574C35.426,10.574 41.276,16.312 41.276,23.39C41.276,30.175 35.902,35.729 29.102,36.178C28.807,36.197 28.51,36.207 28.211,36.207L10.788,36.207"
android:strokeWidth="1.52445396"
android:fillColor="#00000000"
android:strokeColor="#368BD6"
android:fillType="evenOdd"
android:strokeLineCap="round"/>
<path
android:pathData="M17.923,5.702C19.25,7.56 19.76,9.815 19.358,12.048C18.956,14.283 17.691,16.229 15.795,17.531C11.881,20.217 6.467,19.282 3.726,15.445C2.399,13.587 1.889,11.333 2.291,9.099C2.693,6.864 3.958,4.917 5.854,3.617C9.768,0.93 15.182,1.865 17.923,5.702ZM41.347,61.805C38.618,61.805 35.934,60.543 34.248,58.185L22.011,41.052C19.266,37.21 20.217,31.913 24.133,29.222C28.049,26.528 33.449,27.461 36.193,31.303L48.431,48.435C51.175,52.277 50.225,57.574 46.309,60.266C44.797,61.306 43.063,61.805 41.347,61.805Z"
android:strokeWidth="1"
android:fillColor="#368BD6"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>