diff --git a/vector/src/main/java/im/vector/riotx/core/ui/views/JumpToReadMarkerView.kt b/vector/src/main/java/im/vector/riotx/core/ui/views/JumpToReadMarkerView.kt index c44b10e31f..8d461e72af 100644 --- a/vector/src/main/java/im/vector/riotx/core/ui/views/JumpToReadMarkerView.kt +++ b/vector/src/main/java/im/vector/riotx/core/ui/views/JumpToReadMarkerView.kt @@ -21,22 +21,11 @@ package im.vector.riotx.core.ui.views import android.content.Context import android.util.AttributeSet import android.view.View -import android.view.ViewGroup -import android.widget.LinearLayout import android.widget.RelativeLayout import androidx.core.content.ContextCompat import androidx.core.view.isInvisible -import androidx.core.view.isVisible -import androidx.core.view.updateLayoutParams -import butterknife.ButterKnife -import com.airbnb.epoxy.VisibilityState -import com.google.android.material.internal.ViewUtils.dpToPx import im.vector.riotx.R -import im.vector.riotx.features.themes.ThemeUtils import kotlinx.android.synthetic.main.view_jump_to_read_marker.view.* -import me.gujun.android.span.span -import me.saket.bettermovementmethod.BetterLinkMovementMethod -import timber.log.Timber class JumpToReadMarkerView @JvmOverloads constructor( context: Context, diff --git a/vector/src/main/java/im/vector/riotx/core/ui/views/ReadReceiptsView.kt b/vector/src/main/java/im/vector/riotx/core/ui/views/ReadReceiptsView.kt index 2cb0a75e20..517327db62 100644 --- a/vector/src/main/java/im/vector/riotx/core/ui/views/ReadReceiptsView.kt +++ b/vector/src/main/java/im/vector/riotx/core/ui/views/ReadReceiptsView.kt @@ -28,7 +28,7 @@ import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData import kotlinx.android.synthetic.main.view_read_receipts.view.* private const val MAX_RECEIPT_DISPLAYED = 5 -private const val MAX_RECEIPT_DESCRIBED = 4 +private const val MAX_RECEIPT_DESCRIBED = 3 class ReadReceiptsView @JvmOverloads constructor( context: Context, @@ -52,7 +52,6 @@ class ReadReceiptsView @JvmOverloads constructor( setOnClickListener(clickListener) if (readReceipts.isNotEmpty()) { isVisible = true - val displayNames = arrayListOf<String>() for (index in 0 until MAX_RECEIPT_DISPLAYED) { val receiptData = readReceipts.getOrNull(index) if (receiptData == null) { @@ -60,11 +59,14 @@ class ReadReceiptsView @JvmOverloads constructor( } else { receiptAvatars[index].visibility = View.VISIBLE avatarRenderer.render(receiptData.avatarUrl, receiptData.userId, receiptData.displayName, receiptAvatars[index]) - if (null !=receiptData.displayName && displayNames.size <MAX_RECEIPT_DESCRIBED) { - displayNames.add(receiptData.displayName); - } } } + + val displayNames = readReceipts + .mapNotNull { it.displayName } + .filter { it.isNotBlank() } + .take(MAX_RECEIPT_DESCRIBED) + if (readReceipts.size > MAX_RECEIPT_DISPLAYED) { receiptMore.visibility = View.VISIBLE receiptMore.text = context.getString( @@ -73,13 +75,31 @@ class ReadReceiptsView @JvmOverloads constructor( } else { receiptMore.visibility = View.GONE } - when (displayNames.size) { - 0 -> setContentDescription(context.getResources().getQuantityString(R.plurals.fallback_users_read, readReceipts.size)) - 1 -> setContentDescription(context.getString(R.string.one_user_read, displayNames.get(0))) - 2 -> setContentDescription(context.getString(R.string.two_users_read, displayNames.get(0), displayNames.get(1))) - 3 -> setContentDescription(context.getString(R.string.three_users_read, displayNames.get(0), displayNames.get(1), displayNames.get(2))) - else -> setContentDescription(context.getString(R.string.two_and_some_others_read, - displayNames.get(0), displayNames.get(1), (readReceipts.size -2))) + contentDescription = when (readReceipts.size) { + 1 -> + if (displayNames.size == 1) { + context.getString(R.string.one_user_read, displayNames[0]) + } else { + context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + } + 2 -> + if (displayNames.size == 2) { + context.getString(R.string.two_users_read, displayNames[0], displayNames[1]) + } else { + context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + } + 3 -> + if (displayNames.size == 3) { + context.getString(R.string.three_users_read, displayNames[0], displayNames[1], displayNames[2]) + } else { + context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + } + else -> + if (displayNames.size >= 2) { + context.getString(R.string.two_and_some_others_read, displayNames[0], displayNames[1], (readReceipts.size - 2)) + } else { + context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + } } } else { isVisible = false diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index ea5dc83997..8dc9d3948c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -32,6 +32,7 @@ import android.view.inputmethod.InputMethodManager import android.widget.TextView import android.widget.Toast import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityOptionsCompat import androidx.core.content.ContextCompat @@ -79,8 +80,6 @@ import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.ui.views.JumpToReadMarkerView import im.vector.riotx.core.ui.views.NotificationAreaView import im.vector.riotx.core.utils.* -import im.vector.riotx.core.utils.Debouncer -import im.vector.riotx.core.utils.createUIHandler import im.vector.riotx.features.autocomplete.command.AutocompleteCommandPresenter import im.vector.riotx.features.autocomplete.command.CommandAutocompletePolicy import im.vector.riotx.features.autocomplete.user.AutocompleteUserPresenter @@ -362,7 +361,7 @@ class RoomDetailFragment : private fun renderSpecialMode(event: TimelineEvent, @DrawableRes iconRes: Int, - descriptionRes: Int, + @StringRes descriptionRes: Int, defaultContent: String) { commandAutocompletePolicy.enabled = false //switch to expanded bar @@ -376,25 +375,17 @@ class RoomDetailFragment : var formattedBody: CharSequence? = null if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) { val parser = Parser.builder().build() - val document = parser.parse(messageContent.formattedBody - ?: messageContent.body) + val document = parser.parse(messageContent.formattedBody ?: messageContent.body) formattedBody = eventHtmlRenderer.render(document) } - composerLayout.composerRelatedMessageContent.text = formattedBody - ?: nonFormattedBody + composerLayout.composerRelatedMessageContent.text = formattedBody ?: nonFormattedBody updateComposerText(defaultContent) composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes)) composerLayout.sendButton.setContentDescription(getString(descriptionRes)) - - avatarRenderer.render(event.senderAvatar, event.root.senderId - ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar) - avatarRenderer.render(event.senderAvatar, - event.root.senderId ?: "", - event.senderName, - composerLayout.composerRelatedMessageAvatar) + avatarRenderer.render(event.senderAvatar, event.root.senderId ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar) composerLayout.expand { //need to do it here also when not using quick reply focusComposerAndShowKeyboard() @@ -431,10 +422,8 @@ class RoomDetailFragment : when (requestCode) { REQUEST_FILES_REQUEST_CODE, TAKE_IMAGE_REQUEST_CODE -> handleMediaIntent(data) REACTION_SELECT_REQUEST_CODE -> { - val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID) - ?: return - val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT) - ?: return + val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID) ?: return + val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT) ?: return //TODO check if already reacted with that? roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, eventId)) } @@ -596,7 +585,6 @@ class RoomDetailFragment : Timber.w("Send button is locked") return@setOnClickListener } - composerLayout.sendButton.setContentDescription(getString(R.string.send)) val textMessage = composerLayout.composerEditText.text.toString() if (textMessage.isNotBlank()) { lockSendButton = true diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt index c5bc4dd9c8..d562f7ed83 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt @@ -142,8 +142,13 @@ class LoginFragment : VectorBaseFragment() { private fun renderPasswordField() { passwordField.showPassword(passwordShown) - passwordReveal.setImageResource(if (passwordShown) R.drawable.ic_eye_closed_black else R.drawable.ic_eye_black) - passwordReveal.setContentDescription(if (passwordShown) getString(R.string.a11y_hide_password) else getString(R.string.a11y_show_password)) + if (passwordShown) { + passwordReveal.setImageResource(R.drawable.ic_eye_closed_black) + passwordReveal.contentDescription = getString(R.string.a11y_hide_password) + } else { + passwordReveal.setImageResource(R.drawable.ic_eye_black) + passwordReveal.contentDescription = getString(R.string.a11y_show_password) + } } override fun invalidate() = withState(viewModel) { state -> diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiReactionPickerActivity.kt b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiReactionPickerActivity.kt index c9bddbbe72..5407dd22d3 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiReactionPickerActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiReactionPickerActivity.kt @@ -92,10 +92,14 @@ class EmojiReactionPickerActivity : VectorBaseActivity(), EmojiCompatFontProvide it.rawData?.categories?.let { categories -> for (category in categories) { val s = category.emojis[0] - val newTab =tabLayout.newTab() - newTab.setText(it.rawData!!.emojis[s]!!.emojiString()) - newTab.setContentDescription(category.name) - tabLayout.addTab(newTab) + tabLayout.newTab() + .also { tab -> + tab.text = it.rawData!!.emojis[s]!!.emojiString() + tab.contentDescription = category.name + } + .also { tab -> + tabLayout.addTab(tab) + } } tabLayout.addOnTabSelectedListener(tabLayoutSelectionListener) } diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiRecyclerAdapter.kt b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiRecyclerAdapter.kt index cbdbcc11d2..a6f1848b68 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiRecyclerAdapter.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiRecyclerAdapter.kt @@ -132,7 +132,7 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction itemView.setOnClickListener(itemClickListener) val viewHolder = when (viewType) { R.layout.grid_section_header -> SectionViewHolder(itemView) - else -> EmojiViewHolder(itemView) + else -> EmojiViewHolder(itemView) } endTraceSession() return viewHolder @@ -200,7 +200,7 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction val sectionMojis = categories[sectionNumber].emojis val sectionOffset = getSectionOffset(sectionNumber) val emoji = sectionMojis[position - sectionOffset] - val item = dataSource!!.rawData!!.emojis[emoji]!!.emojiString() + val item = dataSource.rawData!!.emojis[emoji]!!.emojiString() (holder as EmojiViewHolder).data = item if (scrollState != ScrollState.SETTLING || !isFastScroll) { // Log.i("PERF","Bind with draw at position:$position") @@ -232,13 +232,13 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction override fun getItemCount(): Int { - dataSource?.rawData?.categories?.let { + return dataSource?.rawData?.categories?.let { var count = /*number of sections*/ it.size for (ad in it) { count += ad.emojis.size } - return count - } ?: kotlin.run { return 0 } + count + } ?: 0 } @@ -258,7 +258,7 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction emojiView.emoji = s if (s != null) { emojiView.mLayout = getStaticLayoutForEmoji(s) - emojiView.setContentDescription(s) + emojiView.contentDescription = s placeHolder.visibility = View.GONE // emojiView.visibility = View.VISIBLE } else { @@ -298,11 +298,10 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction var cachedLayout = staticLayoutCache[emoji] if (cachedLayout == null) { cachedLayout = StaticLayout(emoji, EmojiDrawView.tPaint, EmojiDrawView.emojiSize, Layout.Alignment.ALIGN_CENTER, 1f, 0f, true) - staticLayoutCache[emoji] = cachedLayout!! + staticLayoutCache[emoji] = cachedLayout } - return cachedLayout!! + return cachedLayout } - } interface InteractionListener { @@ -315,10 +314,10 @@ class EmojiRecyclerAdapter(val dataSource: EmojiDataSource? = null, var reaction override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) scrollState = when (newState) { - RecyclerView.SCROLL_STATE_IDLE -> ScrollState.IDLE + RecyclerView.SCROLL_STATE_IDLE -> ScrollState.IDLE RecyclerView.SCROLL_STATE_SETTLING -> ScrollState.SETTLING RecyclerView.SCROLL_STATE_DRAGGING -> ScrollState.DRAGGING - else -> ScrollState.UNKNWON + else -> ScrollState.UNKNWON } //TODO better diff --git a/vector/src/main/res/layout/fragment_login.xml b/vector/src/main/res/layout/fragment_login.xml index a3a1187a64..3dde5e1748 100644 --- a/vector/src/main/res/layout/fragment_login.xml +++ b/vector/src/main/res/layout/fragment_login.xml @@ -87,9 +87,9 @@ android:layout_marginTop="8dp" android:background="?attr/selectableItemBackground" android:scaleType="center" - android:contentDescription="@string/a11y_show_password" android:src="@drawable/ic_eye_black" - android:tint="?attr/colorAccent" /> + android:tint="?attr/colorAccent" + tools:contentDescription="@string/a11y_show_password" /> </FrameLayout> @@ -104,8 +104,8 @@ android:id="@+id/homeServerField" android:layout_width="match_parent" android:layout_height="wrap_content" - android:inputType="textUri" android:imeOptions="actionDone" + android:inputType="textUri" android:maxLines="1" /> </com.google.android.material.textfield.TextInputLayout> diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml index f93ee48990..ab2c40c313 100644 --- a/vector/src/main/res/layout/fragment_room_detail.xml +++ b/vector/src/main/res/layout/fragment_room_detail.xml @@ -6,29 +6,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <FrameLayout - android:id="@+id/syncProgressBarWrap" - android:layout_width="match_parent" - android:layout_height="3dp" - android:visibility="gone" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/roomToolbar" - tools:visibility="visible"> - - <ProgressBar - android:id="@+id/syncProgressBar" - style="@style/Widget.AppCompat.ProgressBar.Horizontal" - android:layout_width="match_parent" - android:layout_height="14dp" - android:layout_gravity="center" - android:background="?riotx_header_panel_background" - android:indeterminate="true" - android:visibility="gone" - tools:visibility="visible" /> - </FrameLayout> - - <!-- Trick to remove surrounding padding (clip frome wrapping frame) --> <androidx.appcompat.widget.Toolbar android:id="@+id/roomToolbar" style="@style/VectorToolbarStyle" @@ -127,7 +104,8 @@ android:visibility="invisible" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/syncStateView" /> + app:layout_constraintTop_toBottomOf="@id/syncStateView" + tools:visibility="visible" /> <im.vector.riotx.core.ui.views.NotificationAreaView android:id="@+id/notificationAreaView" diff --git a/vector/src/main/res/layout/merge_composer_layout.xml b/vector/src/main/res/layout/merge_composer_layout.xml index 95babeb8c7..903ca728b5 100644 --- a/vector/src/main/res/layout/merge_composer_layout.xml +++ b/vector/src/main/res/layout/merge_composer_layout.xml @@ -71,8 +71,8 @@ android:layout_width="22dp" android:layout_height="22dp" android:background="?android:attr/selectableItemBackground" - android:src="@drawable/ic_close_round" android:contentDescription="@string/cancel" + android:src="@drawable/ic_close_round" android:tint="@color/riotx_notice" tools:ignore="MissingConstraints" /> @@ -89,8 +89,8 @@ android:layout_width="0dp" android:layout_height="0dp" android:background="?android:attr/selectableItemBackground" - android:src="@drawable/ic_attachment" android:contentDescription="@string/option_send_files" + android:src="@drawable/ic_attachment" android:tint="?attr/colorAccent" tools:ignore="MissingConstraints" /> diff --git a/vector/src/main/res/layout/view_jump_to_read_marker.xml b/vector/src/main/res/layout/view_jump_to_read_marker.xml index aac22b3311..48f7bd1d80 100644 --- a/vector/src/main/res/layout/view_jump_to_read_marker.xml +++ b/vector/src/main/res/layout/view_jump_to_read_marker.xml @@ -11,13 +11,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toStartOf="@+id/closeJumpToReadMarkerView" + android:background="?attr/selectableItemBackground" android:drawableStart="@drawable/arrow_up_circle" android:drawablePadding="10dp" - android:background="?attr/selectableItemBackground" android:gravity="center_vertical" android:paddingStart="16dp" - android:paddingEnd="16dp" android:paddingTop="12dp" + android:paddingEnd="16dp" android:paddingBottom="12dp" android:text="@string/room_jump_to_first_unread" android:textColor="@color/white" /> @@ -25,12 +25,12 @@ <ImageView android:id="@+id/closeJumpToReadMarkerView" android:layout_width="wrap_content" - android:background="?attr/selectableItemBackground" android:layout_height="match_parent" android:layout_alignTop="@+id/jumpToReadMarkerLabelView" android:layout_alignBottom="@+id/jumpToReadMarkerLabelView" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" + android:background="?attr/selectableItemBackground" android:contentDescription="@string/action_close" android:paddingStart="16dp" android:paddingLeft="16dp" diff --git a/vector/src/main/res/layout/view_read_receipts.xml b/vector/src/main/res/layout/view_read_receipts.xml index 4a6629d43e..cb536884a1 100644 --- a/vector/src/main/res/layout/view_read_receipts.xml +++ b/vector/src/main/res/layout/view_read_receipts.xml @@ -10,12 +10,12 @@ android:id="@+id/receiptMore" android:layout_width="wrap_content" android:layout_height="18dp" - android:gravity="center" - android:textSize="12sp" android:background="?vctr_pill_receipt" + android:gravity="center" + android:importantForAccessibility="no" android:paddingStart="4dp" android:paddingEnd="4dp" - android:importantForAccessibility = "no" + android:textSize="12sp" tools:text="999+" /> <ImageView @@ -24,6 +24,7 @@ android:layout_height="18dp" android:layout_marginStart="2dp" android:adjustViewBounds="true" + android:importantForAccessibility="no" android:scaleType="centerCrop" tools:src="@tools:sample/avatars" /> @@ -33,6 +34,7 @@ android:layout_height="18dp" android:layout_marginStart="2dp" android:adjustViewBounds="true" + android:importantForAccessibility="no" android:scaleType="centerCrop" tools:src="@tools:sample/avatars" /> @@ -42,6 +44,7 @@ android:layout_height="18dp" android:layout_marginStart="2dp" android:adjustViewBounds="true" + android:importantForAccessibility="no" android:scaleType="centerCrop" tools:src="@tools:sample/avatars" /> @@ -51,6 +54,7 @@ android:layout_height="18dp" android:layout_marginStart="2dp" android:adjustViewBounds="true" + android:importantForAccessibility="no" android:scaleType="centerCrop" tools:src="@tools:sample/avatars" /> @@ -60,6 +64,7 @@ android:layout_height="18dp" android:layout_marginStart="2dp" android:adjustViewBounds="true" + android:importantForAccessibility="no" android:scaleType="centerCrop" tools:src="@tools:sample/avatars" /> diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 370b17be22..a66858ae0e 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -26,9 +26,9 @@ <string name="a11y_jump_to_bottom">Jump to bottom</string> <!-- Read receipts list a11y --> - <string name="two_and_some_others_read">%s, %s and %d others read</string> - <string name="three_users_read">%s, %s and %s read</string> - <string name="two_users_read">%s and %s read</string> + <string name="two_and_some_others_read">%1$s, %2$s and %3$d others read</string> + <string name="three_users_read">%1$s, %2$s and %3$s read</string> + <string name="two_users_read">%1$s and %2$s read</string> <string name="one_user_read">%s read</string> <plurals name="fallback_users_read"> <item quantity="one">1 user read</item>