Merge branch 'release/1.3.11' into main

This commit is contained in:
ganfra 2021-12-17 18:53:26 +01:00
commit cab28ffe7e
20 changed files with 117 additions and 60 deletions

View file

@ -1,3 +1,20 @@
Changes in Element v1.3.11 (2021-12-17)
=======================================
Bugfixes 🐛
----------
- Fixing proximity sensor still being active after a call ([#2467](https://github.com/vector-im/element-android/issues/2467))
- Fix name and shield are truncated in the room detail screen ([#4700](https://github.com/vector-im/element-android/issues/4700))
- Call banner: center text vertically ([#4710](https://github.com/vector-im/element-android/issues/4710))
- Fixes unable to render messages by allowing them to render whilst the emoji library is initialising ([#4733](https://github.com/vector-im/element-android/issues/4733))
- Fix app crash uppon long press on a reply event ([#4742](https://github.com/vector-im/element-android/issues/4742))
- Fixes crash when launching rooms which contain emojis in the emote content on android 12+ ([#4743](https://github.com/vector-im/element-android/issues/4743))
Other changes
-------------
- Avoids leaking the activity windows when loading dialogs are displaying ([#4713](https://github.com/vector-im/element-android/issues/4713))
Changes in Element v1.3.10 (2021-12-14)
=======================================

View file

@ -0,0 +1,2 @@
Main changes in this version: Bug fixes!
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.11

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=b75392c5625a88bccd58a574552a5a323edca82dab5942d2d41097f809c6bcce
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip
distributionSha256Sum=dd54e87b4d7aa8ff3c6afb0f7805aa121d4b70bca55b8c9b1b896eb103184582
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -31,7 +31,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.3.10\""
buildConfigField "String", "SDK_VERSION", "\"1.3.11\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""

View file

@ -17,7 +17,7 @@ PARAM_KEYSTORE_PATH=$1
PARAM_APK=$2
# Other params
BUILD_TOOLS_VERSION="31.0.0-rc5"
BUILD_TOOLS_VERSION="31.0.0"
MIN_SDK_VERSION=21
echo "Signing APK with build-tools version ${BUILD_TOOLS_VERSION} for min SDK version ${MIN_SDK_VERSION}..."

View file

@ -23,7 +23,7 @@ PARAM_KS_PASS=$3
PARAM_KEY_PASS=$4
# Other params
BUILD_TOOLS_VERSION="31.0.0-rc5"
BUILD_TOOLS_VERSION="31.0.0"
MIN_SDK_VERSION=21
echo "Signing APK with build-tools version ${BUILD_TOOLS_VERSION} for min SDK version ${MIN_SDK_VERSION}..."

View file

@ -15,7 +15,7 @@ kapt {
// Note: 2 digits max for each value
ext.versionMajor = 1
ext.versionMinor = 3
ext.versionPatch = 10
ext.versionPatch = 11
static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'

View file

@ -24,6 +24,7 @@ import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.text.style.StrikethroughSpan
import android.text.style.UnderlineSpan
import androidx.emoji2.text.EmojiCompat
import im.vector.app.InstrumentedTest
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeTrue
@ -32,12 +33,18 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SpanUtilsTest : InstrumentedTest {
private val spanUtils = SpanUtils()
private val spanUtils = SpanUtils {
val emojiCompat = EmojiCompat.get()
emojiCompat.waitForInit()
emojiCompat.process(it) ?: it
}
private fun SpanUtils.canUseTextFuture(message: CharSequence): Boolean {
return getBindingOptions(message).canUseTextFuture
@ -122,4 +129,17 @@ class SpanUtilsTest : InstrumentedTest {
}
private fun trueIfAlwaysAllowed() = Build.VERSION.SDK_INT < Build.VERSION_CODES.P
private fun EmojiCompat.waitForInit() {
val latch = CountDownLatch(1)
registerInitCallback(object : EmojiCompat.InitCallback() {
override fun onInitialized() = latch.countDown()
override fun onFailed(throwable: Throwable?) {
latch.countDown()
throw RuntimeException(throwable)
}
})
EmojiCompat.init(context())
latch.await(30, TimeUnit.SECONDS)
}
}

View file

@ -23,8 +23,12 @@ import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
fun interface EmojiSpanify {
fun spanify(sequence: CharSequence): CharSequence
}
@Singleton
class EmojiCompatWrapper @Inject constructor(private val context: Context) {
class EmojiCompatWrapper @Inject constructor(private val context: Context) : EmojiSpanify {
private var initialized = false
@ -49,7 +53,7 @@ class EmojiCompatWrapper @Inject constructor(private val context: Context) {
})
}
fun safeEmojiSpanify(sequence: CharSequence): CharSequence {
override fun spanify(sequence: CharSequence): CharSequence {
if (initialized) {
try {
return EmojiCompat.get().process(sequence) ?: sequence

View file

@ -26,6 +26,8 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.EmojiCompatWrapper
import im.vector.app.EmojiSpanify
import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
@ -76,6 +78,9 @@ abstract class VectorBindModule {
@Binds
abstract fun bindDefaultClock(clock: DefaultClock): Clock
@Binds
abstract fun bindEmojiSpanify(emojiCompatWrapper: EmojiCompatWrapper): EmojiSpanify
}
@InstallIn(SingletonComponent::class)

View file

@ -151,6 +151,7 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
override fun onDestroyView() {
Timber.i("onDestroyView Fragment ${javaClass.simpleName}")
_binding = null
dismissLoadingDialog()
super.onDestroyView()
}

View file

@ -93,7 +93,9 @@ class CallProximityManager @Inject constructor(
if (wakeLock == null) {
wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, generateWakeLockTag())
}
wakeLock?.acquire(WAKE_LOCK_TIMEOUT_MILLIS)
wakeLock
?.takeIf { !it.isHeld }
?.acquire(WAKE_LOCK_TIMEOUT_MILLIS)
}
private fun onProximityFar() {

View file

@ -613,7 +613,7 @@ class MessageItemFactory @Inject constructor(
val formattedBody = SpannableStringBuilder()
formattedBody.append("* ${informationData.memberName} ")
formattedBody.append(messageContent.getHtmlBody())
val bindingOptions = spanUtils.getBindingOptions(formattedBody)
val message = formattedBody.linkify(callback)
return MessageTextItem_()
@ -625,6 +625,7 @@ class MessageItemFactory @Inject constructor(
message(message)
}
}
.bindingOptions(bindingOptions)
.leftGuideline(avatarSizeProvider.leftGuideline)
.previewUrlRetriever(callback?.getPreviewUrlRetriever())
.imageContentRenderer(imageContentRenderer)

View file

@ -17,7 +17,7 @@
package im.vector.app.features.home.room.detail.timeline.format
import dagger.Lazy
import im.vector.app.EmojiCompatWrapper
import im.vector.app.EmojiSpanify
import im.vector.app.R
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
@ -39,7 +39,7 @@ import javax.inject.Inject
class DisplayableEventFormatter @Inject constructor(
private val stringProvider: StringProvider,
private val colorProvider: ColorProvider,
private val emojiCompatWrapper: EmojiCompatWrapper,
private val emojiSpanify: EmojiSpanify,
private val noticeEventFormatter: NoticeEventFormatter,
private val htmlRenderer: Lazy<EventHtmlRenderer>
) {
@ -100,7 +100,7 @@ class DisplayableEventFormatter @Inject constructor(
}
EventType.REACTION -> {
timelineEvent.root.getClearContent().toModel<ReactionContent>()?.relatesTo?.let {
val emojiSpanned = emojiCompatWrapper.safeEmojiSpanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
val emojiSpanned = emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
simpleFormat(senderName, emojiSpanned, appendAuthor)
} ?: span { }
}

View file

@ -20,7 +20,7 @@ import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Incomplete
import com.airbnb.mvrx.Success
import im.vector.app.EmojiCompatWrapper
import im.vector.app.EmojiSpanify
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.ui.list.genericFooterItem
@ -32,7 +32,7 @@ import javax.inject.Inject
*/
class ViewReactionsEpoxyController @Inject constructor(
private val stringProvider: StringProvider,
private val emojiCompatWrapper: EmojiCompatWrapper) :
private val emojiSpanify: EmojiSpanify) :
TypedEpoxyController<DisplayReactionsViewState>() {
var listener: Listener? = null
@ -56,7 +56,7 @@ class ViewReactionsEpoxyController @Inject constructor(
reactionInfoSimpleItem {
id(reactionInfo.eventId)
timeStamp(reactionInfo.timestamp)
reactionKey(host.emojiCompatWrapper.safeEmojiSpanify(reactionInfo.reactionKey))
reactionKey(host.emojiSpanify.spanify(reactionInfo.reactionKey))
authorDisplayName(reactionInfo.authorName ?: reactionInfo.authorId)
userClicked { host.listener?.didSelectUser(reactionInfo.authorId) }
}

View file

@ -16,6 +16,7 @@
package im.vector.app.features.home.room.detail.timeline.tools
import android.text.SpannableStringBuilder
import android.text.style.ClickableSpan
import android.view.MotionEvent
import android.widget.TextView
@ -44,7 +45,8 @@ fun CharSequence.findPillsAndProcess(scope: CoroutineScope, processBlock: (PillI
fun CharSequence.linkify(callback: TimelineEventController.UrlClickCallback?): CharSequence {
val text = this.toString()
val spannable = toSpannable()
// SpannableStringBuilder is used to avoid Epoxy throwing ImmutableModelException
val spannable = SpannableStringBuilder(this)
MatrixLinkify.addLinks(spannable, object : MatrixPermalinkSpan.Callback {
override fun onUrlClicked(url: String) {
callback?.onUrlClicked(url, text)

View file

@ -21,13 +21,15 @@ import android.text.Spanned
import android.text.style.MetricAffectingSpan
import android.text.style.StrikethroughSpan
import android.text.style.UnderlineSpan
import androidx.emoji2.text.EmojiCompat
import im.vector.app.EmojiSpanify
import im.vector.app.features.home.room.detail.timeline.item.BindingOptions
import javax.inject.Inject
class SpanUtils @Inject constructor() {
class SpanUtils @Inject constructor(
private val emojiSpanify: EmojiSpanify
) {
fun getBindingOptions(charSequence: CharSequence): BindingOptions {
val emojiCharSequence = EmojiCompat.get().process(charSequence)
val emojiCharSequence = emojiSpanify.spanify(charSequence)
if (emojiCharSequence !is Spanned) {
return BindingOptions()

View file

@ -24,7 +24,7 @@ import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.EmojiCompatWrapper
import im.vector.app.EmojiSpanify
import im.vector.app.R
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.core.utils.TextUtils
@ -41,7 +41,7 @@ class ReactionButton @JvmOverloads constructor(context: Context,
defStyleAttr: Int = 0) :
LinearLayout(context, attrs, defStyleAttr), View.OnClickListener, View.OnLongClickListener {
@Inject lateinit var emojiCompatWrapper: EmojiCompatWrapper
@Inject lateinit var emojiSpanify: EmojiSpanify
private val views: ReactionButtonBinding
@ -57,7 +57,7 @@ class ReactionButton @JvmOverloads constructor(context: Context,
set(value) {
field = value
// maybe cache this for performances?
val emojiSpanned = emojiCompatWrapper.safeEmojiSpanify(value)
val emojiSpanned = emojiSpanify.spanify(value)
views.reactionText.text = emojiSpanned
}

View file

@ -1,25 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:foreground="?attr/selectableItemBackground"
tools:background="?colorPrimary"
tools:parentTag="android.widget.FrameLayout">
<TextView
android:id="@+id/currentCallsInfo"
style="@style/Widget.Vector.TextView.Body"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="10dp"
android:layout_gravity="center"
android:gravity="center"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp"
android:text="@string/call_only_active"
android:textColor="?colorOnPrimary" />
android:textColor="?colorOnPrimary"
tools:text="@string/call_only_active" />
</merge>

View file

@ -12,8 +12,8 @@
android:id="@+id/memberProfileInfoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toTopOf="@id/memberProfileNameView"
app:layout_constraintTop_toTopOf="@id/memberProfileNameView">
@ -23,7 +23,7 @@
android:layout_height="128dp"
android:layout_marginBottom="16dp"
android:contentDescription="@string/avatar"
app:layout_constraintBottom_toTopOf="@id/memberProfileNameView"
app:layout_constraintBottom_toTopOf="@id/memberProfileLinearLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
@ -45,31 +45,37 @@
tools:src="@drawable/ic_presence_offline"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/memberProfileLinearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@id/memberProfileIdView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/memberProfileAvatarView">
<im.vector.app.core.ui.views.ShieldImageView
android:id="@+id/memberProfileDecorationImageView"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@id/memberProfileNameView"
app:layout_constraintEnd_toStartOf="@id/memberProfileNameView"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/memberProfileNameView" />
android:layout_marginEnd="8dp" />
<TextView
android:id="@+id/memberProfileNameView"
style="@style/Widget.Vector.TextView.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:gravity="center"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/memberProfileIdView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/memberProfileDecorationImageView"
app:layout_constraintTop_toBottomOf="@id/memberProfileAvatarView"
tools:text="@sample/users.json/data/displayName" />
</LinearLayout>
<TextView
android:id="@+id/memberProfileIdView"
style="@style/Widget.Vector.TextView.Body"
@ -82,7 +88,7 @@
app:layout_constraintBottom_toTopOf="@id/memberProfilePowerLevelView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/memberProfileNameView"
app:layout_constraintTop_toBottomOf="@id/memberProfileLinearLayout"
tools:text="@sample/users.json/data/id" />
<TextView