mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-18 20:29:10 +03:00
Merge pull request #3031 from vector-im/feature/bma/other_fixies
Some fixies
This commit is contained in:
commit
43fd9910e3
12 changed files with 96 additions and 148 deletions
|
@ -8,9 +8,11 @@ Improvements 🙌:
|
|||
- Split network request `/keys/query` into smaller requests (250 users max) (#2925)
|
||||
- Crypto improvement | Bulk send NO_OLM withheld code
|
||||
- Display the room shield in all room setting screens
|
||||
- Improve message with Emoji only detection (#3017)
|
||||
|
||||
Bugfix 🐛:
|
||||
-
|
||||
- Fix bad theme change for the MainActivity
|
||||
- Handle encrypted reactions (#2509)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
|
|
@ -2,7 +2,7 @@ This document aims to describe how Element android displays notifications to the
|
|||
|
||||
# Table of Contents
|
||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||
* [How does a matrix client gets a message from a Home Server?](#how-does-a-matrix-client-gets-a-message-from-a-home-server)
|
||||
* [How does a matrix client get a message from a Home Server?](#how-does-a-matrix-client-get-a-message-from-a-home-server)
|
||||
* [How does a mobile app receives push notification?](#how-does-a-mobile-app-receives-push-notification)
|
||||
* [Push VS Notification](#push-vs-notification)
|
||||
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
|
||||
|
@ -22,7 +22,7 @@ First let's start with some prerequisite knowledge
|
|||
|
||||
# Prerequisites Knowledge
|
||||
|
||||
## How does a matrix client gets a message from a Home Server?
|
||||
## How does a matrix client get a message from a Home Server?
|
||||
|
||||
In order to get messages from a home server, a matrix client need to perform a ``sync`` operation.
|
||||
|
||||
|
|
|
@ -53,8 +53,9 @@ import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class EventRelationsAggregationProcessor @Inject constructor(@UserId private val userId: String)
|
||||
: EventInsertLiveProcessor {
|
||||
internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||
@UserId private val userId: String
|
||||
) : EventInsertLiveProcessor {
|
||||
|
||||
private val allowedTypes = listOf(
|
||||
EventType.MESSAGE,
|
||||
|
@ -87,12 +88,12 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
EventType.REACTION -> {
|
||||
// we got a reaction!!
|
||||
Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}")
|
||||
handleReaction(event, roomId, realm, userId, isLocalEcho)
|
||||
handleReaction(realm, event, roomId, isLocalEcho)
|
||||
}
|
||||
EventType.MESSAGE -> {
|
||||
if (event.unsignedData?.relations?.annotations != null) {
|
||||
Timber.v("###REACTION Agreggation in room $roomId for event ${event.eventId}")
|
||||
handleInitialAggregatedRelations(event, roomId, event.unsignedData.relations.annotations, realm)
|
||||
Timber.v("###REACTION Aggregation in room $roomId for event ${event.eventId}")
|
||||
handleInitialAggregatedRelations(realm, event, roomId, event.unsignedData.relations.annotations)
|
||||
|
||||
EventAnnotationsSummaryEntity.where(realm, roomId, event.eventId ?: "").findFirst()
|
||||
?.let {
|
||||
|
@ -108,7 +109,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
handleReplace(realm, event, content, roomId, isLocalEcho)
|
||||
} else if (content?.relatesTo?.type == RelationType.RESPONSE) {
|
||||
Timber.v("###RESPONSE in room $roomId for event ${event.eventId}")
|
||||
handleResponse(realm, userId, event, content, roomId, isLocalEcho)
|
||||
handleResponse(realm, event, content, roomId, isLocalEcho)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +123,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
Timber.v("## SAS REF in room $roomId for event ${event.eventId}")
|
||||
event.content.toModel<MessageRelationContent>()?.relatesTo?.let {
|
||||
if (it.type == RelationType.REFERENCE && it.eventId != null) {
|
||||
handleVerification(realm, event, roomId, isLocalEcho, it.eventId, userId)
|
||||
handleVerification(realm, event, roomId, isLocalEcho, it.eventId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
handleReplace(realm, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId)
|
||||
} else if (encryptedEventContent.relatesTo.type == RelationType.RESPONSE) {
|
||||
Timber.v("###RESPONSE in room $roomId for event ${event.eventId}")
|
||||
handleResponse(realm, userId, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId)
|
||||
handleResponse(realm, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId)
|
||||
}
|
||||
}
|
||||
} else if (encryptedEventContent?.relatesTo?.type == RelationType.REFERENCE) {
|
||||
|
@ -154,10 +155,17 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
EventType.KEY_VERIFICATION_KEY -> {
|
||||
Timber.v("## SAS REF in room $roomId for event ${event.eventId}")
|
||||
encryptedEventContent.relatesTo.eventId?.let {
|
||||
handleVerification(realm, event, roomId, isLocalEcho, it, userId)
|
||||
handleVerification(realm, event, roomId, isLocalEcho, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (encryptedEventContent?.relatesTo?.type == RelationType.ANNOTATION) {
|
||||
// Reaction
|
||||
if (event.getClearType() == EventType.REACTION) {
|
||||
// we got a reaction!!
|
||||
Timber.v("###REACTION e2e in room $roomId , reaction eventID ${event.eventId}")
|
||||
handleReaction(realm, event, roomId, isLocalEcho)
|
||||
}
|
||||
}
|
||||
}
|
||||
EventType.REDACTION -> {
|
||||
|
@ -172,11 +180,11 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
// was this event a m.replace
|
||||
val contentModel = ContentMapper.map(eventToPrune.content)?.toModel<MessageContent>()
|
||||
if (RelationType.REPLACE == contentModel?.relatesTo?.type && contentModel.relatesTo?.eventId != null) {
|
||||
handleRedactionOfReplace(eventToPrune, contentModel.relatesTo!!.eventId!!, realm)
|
||||
handleRedactionOfReplace(realm, eventToPrune, contentModel.relatesTo!!.eventId!!)
|
||||
}
|
||||
}
|
||||
EventType.REACTION -> {
|
||||
handleReactionRedact(eventToPrune, realm, userId)
|
||||
handleReactionRedact(realm, eventToPrune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +275,6 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
}
|
||||
|
||||
private fun handleResponse(realm: Realm,
|
||||
userId: String,
|
||||
event: Event,
|
||||
content: MessageContent,
|
||||
roomId: String,
|
||||
|
@ -354,7 +361,10 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
existingPollSummary.aggregatedContent = ContentMapper.map(sumModel.toContent())
|
||||
}
|
||||
|
||||
private fun handleInitialAggregatedRelations(event: Event, roomId: String, aggregation: AggregatedAnnotation, realm: Realm) {
|
||||
private fun handleInitialAggregatedRelations(realm: Realm,
|
||||
event: Event,
|
||||
roomId: String,
|
||||
aggregation: AggregatedAnnotation) {
|
||||
if (SHOULD_HANDLE_SERVER_AGREGGATION) {
|
||||
aggregation.chunk?.forEach {
|
||||
if (it.type == EventType.REACTION) {
|
||||
|
@ -376,7 +386,10 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleReaction(event: Event, roomId: String, realm: Realm, userId: String, isLocalEcho: Boolean) {
|
||||
private fun handleReaction(realm: Realm,
|
||||
event: Event,
|
||||
roomId: String,
|
||||
isLocalEcho: Boolean) {
|
||||
val content = event.content.toModel<ReactionContent>()
|
||||
if (content == null) {
|
||||
Timber.e("Malformed reaction content ${event.content}")
|
||||
|
@ -441,7 +454,9 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
/**
|
||||
* Called when an event is deleted
|
||||
*/
|
||||
private fun handleRedactionOfReplace(redacted: EventEntity, relatedEventId: String, realm: Realm) {
|
||||
private fun handleRedactionOfReplace(realm: Realm,
|
||||
redacted: EventEntity,
|
||||
relatedEventId: String) {
|
||||
Timber.d("Handle redaction of m.replace")
|
||||
val eventSummary = EventAnnotationsSummaryEntity.where(realm, redacted.roomId, relatedEventId).findFirst()
|
||||
if (eventSummary == null) {
|
||||
|
@ -457,7 +472,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
sourceToDiscard.deleteFromRealm()
|
||||
}
|
||||
|
||||
private fun handleReactionRedact(eventToPrune: EventEntity, realm: Realm, userId: String) {
|
||||
private fun handleReactionRedact(realm: Realm,
|
||||
eventToPrune: EventEntity) {
|
||||
Timber.v("REDACTION of reaction ${eventToPrune.eventId}")
|
||||
// delete a reaction, need to update the annotation summary if any
|
||||
val reactionContent: ReactionContent = EventMapper.map(eventToPrune).content.toModel() ?: return
|
||||
|
@ -494,7 +510,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleVerification(realm: Realm, event: Event, roomId: String, isLocalEcho: Boolean, relatedEventId: String, userId: String) {
|
||||
private fun handleVerification(realm: Realm, event: Event, roomId: String, isLocalEcho: Boolean, relatedEventId: String) {
|
||||
val eventSummary = EventAnnotationsSummaryEntity.getOrCreate(realm, roomId, relatedEventId)
|
||||
|
||||
val verifSummary = eventSummary.referencesSummaryEntity
|
||||
|
|
|
@ -16,62 +16,7 @@
|
|||
|
||||
package im.vector.app.core.utils
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
private val emojisPattern = Pattern.compile("((?:[\uD83C\uDF00-\uD83D\uDDFF]" +
|
||||
"|[\uD83E\uDD00-\uD83E\uDDFF]" +
|
||||
"|[\uD83D\uDE00-\uD83D\uDE4F]" +
|
||||
"|[\uD83D\uDE80-\uD83D\uDEFF]" +
|
||||
"|[\u2600-\u26FF]\uFE0F?" +
|
||||
"|[\u2700-\u27BF]\uFE0F?" +
|
||||
"|\u24C2\uFE0F?" +
|
||||
"|[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}" +
|
||||
"|[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?" +
|
||||
"|[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3" +
|
||||
"|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?" +
|
||||
"|[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?" +
|
||||
"|[\u2934\u2935]\uFE0F?" +
|
||||
"|[\u3030\u303D]\uFE0F?" +
|
||||
"|[\u3297\u3299]\uFE0F?" +
|
||||
"|[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?" +
|
||||
"|[\u203C\u2049]\uFE0F?" +
|
||||
"|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?" +
|
||||
"|[\u00A9\u00AE]\uFE0F?" +
|
||||
"|[\u2122\u2139]\uFE0F?" +
|
||||
"|\uD83C\uDC04\uFE0F?" +
|
||||
"|\uD83C\uDCCF\uFE0F?" +
|
||||
"|[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?))")
|
||||
|
||||
/*
|
||||
// A hashset from all supported emoji
|
||||
private var knownEmojiSet: HashSet<String>? = null
|
||||
|
||||
fun initKnownEmojiHashSet(context: Context, done: (() -> Unit)? = null) {
|
||||
GlobalScope.launch {
|
||||
context.resources.openRawResource(R.raw.emoji_picker_datasource).use { input ->
|
||||
val moshi = Moshi.Builder().build()
|
||||
val jsonAdapter = moshi.adapter(EmojiData::class.java)
|
||||
val inputAsString = input.bufferedReader().use { it.readText() }
|
||||
val source = jsonAdapter.fromJson(inputAsString)
|
||||
knownEmojiSet = HashSet<String>().also {
|
||||
source?.emojis?.mapTo(it) { (_, value) ->
|
||||
value.emojiString()
|
||||
}
|
||||
}
|
||||
done?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isSingleEmoji(string: String): Boolean {
|
||||
if (knownEmojiSet == null) {
|
||||
Timber.e("Known Emoji Hashset not initialized")
|
||||
// use fallback regexp
|
||||
return containsOnlyEmojis(string)
|
||||
}
|
||||
return knownEmojiSet?.contains(string) ?: false
|
||||
}
|
||||
*/
|
||||
import com.vanniktech.emoji.EmojiUtils
|
||||
|
||||
/**
|
||||
* Test if a string contains emojis.
|
||||
|
@ -82,36 +27,8 @@ fun isSingleEmoji(string: String): Boolean {
|
|||
* @return true if the body contains only emojis
|
||||
*/
|
||||
fun containsOnlyEmojis(str: String?): Boolean {
|
||||
var res = false
|
||||
|
||||
if (str != null && str.isNotEmpty()) {
|
||||
val matcher = emojisPattern.matcher(str)
|
||||
|
||||
var start = -1
|
||||
var end = -1
|
||||
|
||||
while (matcher.find()) {
|
||||
val nextStart = matcher.start()
|
||||
|
||||
// first emoji position
|
||||
if (start < 0) {
|
||||
if (nextStart > 0) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
// must not have a character between
|
||||
if (nextStart != end) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
start = nextStart
|
||||
end = matcher.end()
|
||||
}
|
||||
|
||||
res = -1 != start && end == str.length
|
||||
}
|
||||
|
||||
return res
|
||||
// Now rely on vanniktech library
|
||||
return EmojiUtils.isOnlyEmojis(str)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,6 +43,7 @@ import im.vector.app.features.popup.PopupAlertManager
|
|||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.signout.hard.SignedOutActivity
|
||||
import im.vector.app.features.signout.soft.SoftLogoutActivity
|
||||
import im.vector.app.features.themes.ActivityOtherThemes
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -83,6 +84,8 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
|
|||
|
||||
override fun getBinding() = ActivityMainBinding.inflate(layoutInflater)
|
||||
|
||||
override fun getOtherThemes() = ActivityOtherThemes.Launcher
|
||||
|
||||
private lateinit var args: MainActivityArgs
|
||||
|
||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||
|
|
|
@ -30,10 +30,8 @@ import im.vector.app.R
|
|||
import im.vector.app.core.extensions.showPassword
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.utils.colorizeMatchingText
|
||||
import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -59,8 +57,9 @@ class SharedSecuredStoragePassphraseFragment @Inject constructor(
|
|||
key
|
||||
)
|
||||
.toSpannable()
|
||||
.colorizeMatchingText(pass, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
.colorizeMatchingText(key, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
// TODO Restore coloration when we will have a FAQ to open with those terms
|
||||
// .colorizeMatchingText(pass, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
// .colorizeMatchingText(key, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
|
||||
views.ssssPassphraseEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
|
|
|
@ -119,13 +119,18 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
Timber.v("## SAS verificationRequestCreated ${pr.transactionId}")
|
||||
// For incoming request we should prompt (if not in activity where this request apply)
|
||||
if (pr.isIncoming) {
|
||||
val user = session?.getUser(pr.otherUserId)
|
||||
val user = session?.getUser(pr.otherUserId)?.toMatrixItem()
|
||||
val name = user?.getBestName() ?: pr.otherUserId
|
||||
val description = if (name == pr.otherUserId) {
|
||||
name
|
||||
} else {
|
||||
"$name (${pr.otherUserId})"
|
||||
}
|
||||
|
||||
val alert = VerificationVectorAlert(
|
||||
uniqueIdForVerificationRequest(pr),
|
||||
context.getString(R.string.sas_incoming_request_notif_title),
|
||||
"$name(${pr.otherUserId})",
|
||||
description,
|
||||
R.drawable.ic_shield_black,
|
||||
shouldBeDisplayedIn = { activity ->
|
||||
if (activity is RoomDetailActivity) {
|
||||
|
@ -136,7 +141,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
}
|
||||
)
|
||||
.apply {
|
||||
viewBinder = VerificationVectorAlert.ViewBinder(user?.toMatrixItem(), avatarRenderer.get())
|
||||
viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer.get())
|
||||
contentAction = Runnable {
|
||||
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
|
||||
val roomId = pr.roomId
|
||||
|
|
|
@ -64,7 +64,6 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||
EventType.STATE_ROOM_SERVER_ACL,
|
||||
EventType.STATE_ROOM_GUEST_ACCESS,
|
||||
EventType.STATE_ROOM_POWER_LEVELS,
|
||||
EventType.REACTION,
|
||||
EventType.REDACTION -> noticeItemFactory.create(event, highlight, callback)
|
||||
EventType.STATE_ROOM_WIDGET_LEGACY,
|
||||
EventType.STATE_ROOM_WIDGET -> widgetItemFactory.create(event, highlight, callback)
|
||||
|
@ -91,6 +90,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||
EventType.KEY_VERIFICATION_KEY,
|
||||
EventType.KEY_VERIFICATION_READY,
|
||||
EventType.KEY_VERIFICATION_MAC,
|
||||
EventType.REACTION,
|
||||
EventType.CALL_CANDIDATES,
|
||||
EventType.CALL_REPLACES,
|
||||
EventType.CALL_SELECT_ANSWER,
|
||||
|
|
|
@ -26,6 +26,7 @@ import im.vector.app.R
|
|||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.utils.isAnimationDisabled
|
||||
import im.vector.app.features.pin.PinActivity
|
||||
import im.vector.app.features.signout.hard.SignedOutActivity
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import timber.log.Timber
|
||||
import java.lang.ref.WeakReference
|
||||
|
@ -294,6 +295,7 @@ class PopupAlertManager @Inject constructor() {
|
|||
private fun shouldBeDisplayedIn(alert: VectorAlert?, activity: Activity): Boolean {
|
||||
return alert != null
|
||||
&& activity !is PinActivity
|
||||
&& activity !is SignedOutActivity
|
||||
&& activity is VectorBaseActivity<*>
|
||||
&& alert.shouldBeDisplayedIn.invoke(activity)
|
||||
}
|
||||
|
|
|
@ -222,7 +222,6 @@ class RoomProfileController @Inject constructor(
|
|||
buildProfileAction(
|
||||
id = "devTools",
|
||||
title = stringProvider.getString(R.string.dev_tools_menu_name),
|
||||
subtitle = roomSummary.roomId,
|
||||
dividerColor = dividerColor,
|
||||
divider = false,
|
||||
editable = true,
|
||||
|
|
|
@ -31,6 +31,11 @@ sealed class ActivityOtherThemes(@StyleRes val dark: Int,
|
|||
R.style.AppTheme_Black
|
||||
)
|
||||
|
||||
object Launcher : ActivityOtherThemes(
|
||||
R.style.AppTheme_Launcher,
|
||||
R.style.AppTheme_Launcher
|
||||
)
|
||||
|
||||
object AttachmentsPreview : ActivityOtherThemes(
|
||||
R.style.AppTheme_AttachmentsPreview,
|
||||
R.style.AppTheme_AttachmentsPreview
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingBottom="32dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ssss_shield"
|
||||
|
@ -28,7 +30,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="36dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/recovery_passphrase"
|
||||
android:textColor="?riotx_text_primary"
|
||||
|
@ -38,7 +39,6 @@
|
|||
app:layout_constraintStart_toEndOf="@id/ssss_shield"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ssss_restore_with_passphrase_warning_text"
|
||||
android:layout_width="0dp"
|
||||
|
@ -51,7 +51,6 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/ssss_restore_with_passphrase"
|
||||
tools:text="@string/enter_secret_storage_passphrase_or_key" />
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/ssss_passphrase_enter_til"
|
||||
style="@style/VectorTextInputLayout"
|
||||
|
@ -82,61 +81,62 @@
|
|||
android:layout_width="@dimen/layout_touch_size"
|
||||
android:layout_height="@dimen/layout_touch_size"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:scaleType="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ssss_passphrase_enter_til"
|
||||
app:layout_constraintTop_toTopOf="@+id/ssss_passphrase_enter_til"
|
||||
app:tint="?colorAccent" />
|
||||
|
||||
<!-- -->
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/ssss_passphrase_use_key"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/use_recovery_key"
|
||||
app:icon="@drawable/ic_security_key_24dp"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/ssss_passphrase_submit"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/_continue"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<androidx.constraintlayout.helper.widget.Flow
|
||||
android:id="@+id/ssss_passphrase_flow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
app:constraint_referenced_ids="ssss_passphrase_use_key,ssss_passphrase_submit"
|
||||
app:flow_horizontalStyle="spread_inside"
|
||||
app:flow_wrapMode="chain"
|
||||
android:text="@string/_continue"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ssss_passphrase_enter_til" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ssss_passphrase_or"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/or"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ssss_passphrase_submit" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/ssss_passphrase_use_key"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/use_recovery_key"
|
||||
app:icon="@drawable/ic_security_key_24dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/ssss_passphrase_reset"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ssss_passphrase_enter_til"
|
||||
app:layout_goneMarginBottom="32dp" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ssss_passphrase_or" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
android:id="@+id/ssss_passphrase_reset"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:actionTitle="@string/bad_passphrase_key_reset_all_action"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/ssss_passphrase_flow"
|
||||
app:layout_constraintTop_toBottomOf="@id/ssss_passphrase_use_key"
|
||||
app:leftIcon="@drawable/ic_alert_triangle"
|
||||
app:tint="@color/vector_error_color"
|
||||
app:titleTextColor="?riotx_text_secondary" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
Loading…
Add table
Reference in a new issue