diff --git a/changelog.d/3547.feature b/changelog.d/3547.feature
new file mode 100644
index 0000000000..8921932067
--- /dev/null
+++ b/changelog.d/3547.feature
@@ -0,0 +1 @@
+Implements new design for Jump to unread and quick fix visibility issues.
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/styles_jump_to_unread.xml b/library/ui-styles/src/main/res/values/styles_jump_to_unread.xml
new file mode 100644
index 0000000000..21f0ebd5d4
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/styles_jump_to_unread.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml
index 8fffb9f05f..9d2d37d331 100644
--- a/library/ui-styles/src/main/res/values/theme_dark.xml
+++ b/library/ui-styles/src/main/res/values/theme_dark.xml
@@ -132,6 +132,9 @@
- @style/Widget.Vector.Button.Outlined.SocialLogin.Twitter.Dark
- @style/Widget.Vector.Button.Outlined.SocialLogin.Apple.Dark
- @style/Widget.Vector.Button.Outlined.SocialLogin.Gitlab.Dark
+
+ - @style/Widget.Vector.JumpToUnread.Dark
+
diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml
index 41786ca030..90338f6178 100644
--- a/library/ui-styles/src/main/res/values/theme_light.xml
+++ b/library/ui-styles/src/main/res/values/theme_light.xml
@@ -134,6 +134,9 @@
- @style/Widget.Vector.Button.Outlined.SocialLogin.Twitter.Light
- @style/Widget.Vector.Button.Outlined.SocialLogin.Apple.Light
- @style/Widget.Vector.Button.Outlined.SocialLogin.Gitlab.Light
+
+ - @style/Widget.Vector.JumpToUnread.Light
+
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/JumpToReadMarkerView.kt b/vector/src/main/java/im/vector/app/core/ui/views/JumpToReadMarkerView.kt
deleted file mode 100644
index 28e23c0e50..0000000000
--- a/vector/src/main/java/im/vector/app/core/ui/views/JumpToReadMarkerView.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2019 New Vector Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package im.vector.app.core.ui.views
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.widget.RelativeLayout
-import androidx.core.content.ContextCompat
-import im.vector.app.R
-import im.vector.app.databinding.ViewJumpToReadMarkerBinding
-
-class JumpToReadMarkerView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : RelativeLayout(context, attrs, defStyleAttr) {
-
- interface Callback {
- fun onJumpToReadMarkerClicked()
- fun onClearReadMarkerClicked()
- }
-
- var callback: Callback? = null
-
- init {
- setupView()
- }
-
- private fun setupView() {
- inflate(context, R.layout.view_jump_to_read_marker, this)
- val views = ViewJumpToReadMarkerBinding.bind(this)
- setBackgroundColor(ContextCompat.getColor(context, R.color.notification_accent_color))
- views.jumpToReadMarkerLabelView.setOnClickListener {
- callback?.onJumpToReadMarkerClicked()
- }
- views.closeJumpToReadMarkerView.setOnClickListener {
- visibility = View.INVISIBLE
- callback?.onClearReadMarkerClicked()
- }
- }
-}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index e1e5efa58c..3d99dc785f 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -92,7 +92,6 @@ import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.ui.views.ActiveConferenceView
import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.FailedMessagesWarningView
-import im.vector.app.core.ui.views.JumpToReadMarkerView
import im.vector.app.core.ui.views.KnownCallsViewHolder
import im.vector.app.core.ui.views.NotificationAreaView
import im.vector.app.core.utils.Debouncer
@@ -237,7 +236,6 @@ class RoomDetailFragment @Inject constructor(
VectorBaseFragment(),
TimelineEventController.Callback,
VectorInviteView.Callback,
- JumpToReadMarkerView.Callback,
AttachmentTypeSelectorView.Callback,
AttachmentsHelper.Callback,
GalleryOrCameraDialogHelper.Listener,
@@ -354,6 +352,10 @@ class RoomDetailFragment @Inject constructor(
renderTombstoneEventHandling(it)
}
+ roomDetailViewModel.selectSubscribe(RoomDetailViewState::canShowJumpToReadMarker, RoomDetailViewState::unreadState) { _, _ ->
+ updateJumpToReadMarkerViewVisibility()
+ }
+
roomDetailViewModel.selectSubscribe(RoomDetailViewState::sendMode, RoomDetailViewState::canSendMessage) { mode, canSend ->
if (!canSend) {
return@selectSubscribe
@@ -723,7 +725,12 @@ class RoomDetailFragment @Inject constructor(
}
private fun setupJumpToReadMarkerView() {
- views.jumpToReadMarkerView.callback = this
+ views.jumpToReadMarkerView.setOnClickListener {
+ onJumpToReadMarkerClicked()
+ }
+ views.jumpToReadMarkerView.setOnCloseIconClickListener {
+ roomDetailViewModel.handle(RoomDetailAction.MarkAllAsRead)
+ }
}
private fun setupActiveCallView() {
@@ -1052,7 +1059,13 @@ class RoomDetailFragment @Inject constructor(
timelineEventController.timeline = roomDetailViewModel.timeline
views.timelineRecyclerView.trackItemsVisibilityChange()
- layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, true)
+ layoutManager = object : LinearLayoutManager(context, RecyclerView.VERTICAL, true) {
+ override fun onLayoutCompleted(state: RecyclerView.State?) {
+ super.onLayoutCompleted(state)
+ updateJumpToReadMarkerViewVisibility()
+ jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay()
+ }
+ }
val stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager, timelineEventController)
scrollOnHighlightedEventCallback = ScrollOnHighlightedEventCallback(views.timelineRecyclerView, layoutManager, timelineEventController)
@@ -1063,8 +1076,6 @@ class RoomDetailFragment @Inject constructor(
it.dispatchTo(stateRestorer)
it.dispatchTo(scrollOnNewMessageCallback)
it.dispatchTo(scrollOnHighlightedEventCallback)
- updateJumpToReadMarkerViewVisibility()
- jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay()
}
timelineEventController.addModelBuildListener(modelBuildListener)
views.timelineRecyclerView.adapter = timelineEventController.adapter
@@ -1120,7 +1131,7 @@ class RoomDetailFragment @Inject constructor(
is UnreadState.ReadMarkerNotLoaded -> true
is UnreadState.HasUnread -> {
if (it.canShowJumpToReadMarker) {
- val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
+ val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition()
val positionOfReadMarker = timelineEventController.getPositionOfReadMarker()
if (positionOfReadMarker == null) {
false
@@ -1692,7 +1703,6 @@ class RoomDetailFragment @Inject constructor(
}
override fun onReadMarkerVisible() {
- updateJumpToReadMarkerViewVisibility()
roomDetailViewModel.handle(RoomDetailAction.EnterTrackingUnreadMessagesState)
}
@@ -1951,10 +1961,7 @@ class RoomDetailFragment @Inject constructor(
roomDetailViewModel.handle(RoomDetailAction.RejectInvite)
}
-// JumpToReadMarkerView.Callback
-
- override fun onJumpToReadMarkerClicked() = withState(roomDetailViewModel) {
- views.jumpToReadMarkerView.isVisible = false
+ private fun onJumpToReadMarkerClicked() = withState(roomDetailViewModel) {
if (it.unreadState is UnreadState.HasUnread) {
roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(it.unreadState.firstUnreadEventId, false))
}
@@ -1963,10 +1970,6 @@ class RoomDetailFragment @Inject constructor(
}
}
- override fun onClearReadMarkerClicked() {
- roomDetailViewModel.handle(RoomDetailAction.MarkAllAsRead)
- }
-
// AttachmentTypeSelectorView.Callback
private val typeSelectedActivityResultLauncher = registerForPermissionsResult { allGranted ->
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
index 69aa1e83d3..2cb0f99c50 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
@@ -1243,6 +1243,7 @@ class RoomDetailViewModel @AssistedInject constructor(
}
private fun handleMarkAllAsRead() {
+ setState { copy(unreadState = UnreadState.HasNoUnread) }
viewModelScope.launch {
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.BOTH) }
}
@@ -1379,7 +1380,6 @@ class RoomDetailViewModel @AssistedInject constructor(
}
}
.subscribe {
- Timber.v("Unread state: $it")
setState { copy(unreadState = it) }
}
.disposeOnClear()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/ScrollOnHighlightedEventCallback.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/ScrollOnHighlightedEventCallback.kt
index 5d3a91f18d..7f652a2eea 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/ScrollOnHighlightedEventCallback.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/ScrollOnHighlightedEventCallback.kt
@@ -20,7 +20,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import im.vector.app.core.platform.DefaultListUpdateCallback
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
-import timber.log.Timber
import java.util.concurrent.atomic.AtomicReference
/**
@@ -42,19 +41,10 @@ class ScrollOnHighlightedEventCallback(private val recyclerView: RecyclerView,
private fun scrollIfNeeded() {
val eventId = scheduledEventId.get() ?: return
- val positionToScroll = timelineEventController.searchPositionOfEvent(eventId)
- if (positionToScroll != null) {
- val firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition()
- val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition()
-
- // Do not scroll it item is already visible
- if (positionToScroll !in firstVisibleItem..lastVisibleItem) {
- Timber.v("Scroll to $positionToScroll")
- recyclerView.stopScroll()
- layoutManager.scrollToPosition(positionToScroll)
- }
- scheduledEventId.set(null)
- }
+ val positionToScroll = timelineEventController.searchPositionOfEvent(eventId) ?: return
+ recyclerView.stopScroll()
+ layoutManager.scrollToPosition(positionToScroll)
+ scheduledEventId.set(null)
}
fun scheduleScrollTo(eventId: String?) {
diff --git a/vector/src/main/res/drawable-hdpi/arrow_up_circle.png b/vector/src/main/res/drawable-hdpi/arrow_up_circle.png
deleted file mode 100755
index c7fba081c1..0000000000
Binary files a/vector/src/main/res/drawable-hdpi/arrow_up_circle.png and /dev/null differ
diff --git a/vector/src/main/res/drawable-mdpi/arrow_up_circle.png b/vector/src/main/res/drawable-mdpi/arrow_up_circle.png
deleted file mode 100755
index aad94e9a4e..0000000000
Binary files a/vector/src/main/res/drawable-mdpi/arrow_up_circle.png and /dev/null differ
diff --git a/vector/src/main/res/drawable-xhdpi/arrow_up_circle.png b/vector/src/main/res/drawable-xhdpi/arrow_up_circle.png
deleted file mode 100755
index 8973128ccc..0000000000
Binary files a/vector/src/main/res/drawable-xhdpi/arrow_up_circle.png and /dev/null differ
diff --git a/vector/src/main/res/drawable-xxhdpi/arrow_up_circle.png b/vector/src/main/res/drawable-xxhdpi/arrow_up_circle.png
deleted file mode 100755
index c13179d220..0000000000
Binary files a/vector/src/main/res/drawable-xxhdpi/arrow_up_circle.png and /dev/null differ
diff --git a/vector/src/main/res/drawable-xxxhdpi/arrow_up_circle.png b/vector/src/main/res/drawable-xxxhdpi/arrow_up_circle.png
deleted file mode 100755
index 61fd2b1e48..0000000000
Binary files a/vector/src/main/res/drawable-xxxhdpi/arrow_up_circle.png and /dev/null differ
diff --git a/vector/src/main/res/drawable/ic_jump_to_unread.xml b/vector/src/main/res/drawable/ic_jump_to_unread.xml
new file mode 100644
index 0000000000..2c5b8b90c1
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_jump_to_unread.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml
index 19d85d5393..59d1fbfb32 100644
--- a/vector/src/main/res/layout/fragment_room_detail.xml
+++ b/vector/src/main/res/layout/fragment_room_detail.xml
@@ -127,32 +127,22 @@
app:layout_constraintTop_toBottomOf="@id/activeConferenceView"
tools:listitem="@layout/item_timeline_event_base" />
-
+ app:layout_constraintTop_toBottomOf="@id/activeConferenceView"
+ tools:visibility="visible" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/jumpToReadMarkerView">
-
-
-
-
-
-
-
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 3f2cc17acc..6908fe5d79 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -783,7 +783,7 @@
List members
Open header
Syncing…
- Jump to first unread message.
+ Jump to unread
You have been invited to join this room by %s