diff --git a/CHANGELOG.md b/CHANGELOG.md index 73dae8c45..b021ada36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Group changes to describe their impact on the project, as follows: ### Changed - UI has been reworked around SlidingPane component to better handle tablets & foldable devices +- No longer scroll to bottom of chat room when new messages are received, a new button shows up to do it - Animations have been replaced to use com.google.android.material.transition ones - Using new [Unified Content API](https://developer.android.com/about/versions/12/features/unified-content-api) to share files from keyboard (or other sources) - Bumped dependencies, gradle updated from 4.2.2 to 7.0.2 diff --git a/app/src/main/java/org/linphone/activities/main/chat/ChatScrollListener.kt b/app/src/main/java/org/linphone/activities/main/chat/ChatScrollListener.kt index 7b2598b83..21a97ebcf 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/ChatScrollListener.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/ChatScrollListener.kt @@ -29,6 +29,8 @@ internal abstract class ChatScrollListener(private val mLayoutManager: LinearLay // True if we are still waiting for the last set of data to load. private var loading = true + var userHasScrolledUp: Boolean = false + // This happens many times a second during a scroll, so be wary of the code you place here. // We are given a few useful parameters to help us work out if we need to load some more data, // but first we check if we are waiting for the previous load to finish. @@ -54,6 +56,13 @@ internal abstract class ChatScrollListener(private val mLayoutManager: LinearLay previousTotalItemCount = totalItemCount } + userHasScrolledUp = lastVisibleItemPosition != totalItemCount - 1 + if (userHasScrolledUp) { + onScrolledUp() + } else { + onScrolledToEnd() + } + // If it isn’t currently loading, we check to see if we have breached // the mVisibleThreshold and need to reload more data. // If we do need to reload some more data, we execute onLoadMore to fetch the data. @@ -67,6 +76,12 @@ internal abstract class ChatScrollListener(private val mLayoutManager: LinearLay // Defines the process for actually loading more data based on page protected abstract fun onLoadMore(totalItemsCount: Int) + // Called when user has started to scroll up, opposed to onScrolledToEnd() + protected abstract fun onScrolledUp() + + // Called when user has scrolled and reached the end of the items + protected abstract fun onScrolledToEnd() + companion object { // The minimum amount of items to have below your current scroll position // before loading more. diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 10882e4ae..39b9a6219 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -75,8 +75,15 @@ class DetailChatRoomFragment : MasterFragment 0) { + binding.chatMessagesList.smoothScrollToPosition(adapter.itemCount - 1) + } + } + private fun pickFile() { val intentsList = ArrayList() diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt index 8aa80622a..b030e600b 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt @@ -23,6 +23,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import java.util.* +import kotlin.math.max import org.linphone.activities.main.chat.data.EventLogData import org.linphone.core.* import org.linphone.core.tools.Log @@ -212,7 +213,10 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { private fun getEvents(): ArrayList { val list = arrayListOf() - val history = chatRoom.getHistoryEvents(MESSAGES_PER_PAGE) + val unreadCount = chatRoom.unreadMessagesCount + val loadCount = max(MESSAGES_PER_PAGE, unreadCount) + Log.i("[Chat Messages] $unreadCount unread messages in this chat room, loading $loadCount from history") + val history = chatRoom.getHistoryEvents(loadCount) for (eventLog in history) { list.add(EventLogData(eventLog)) } diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomViewModel.kt index 6e16530c3..5194d5f08 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomViewModel.kt @@ -19,10 +19,13 @@ */ package org.linphone.activities.main.chat.viewmodels +import android.animation.ValueAnimator +import android.view.animation.LinearInterpolator import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.contact.Contact import org.linphone.contact.ContactDataInterface @@ -81,12 +84,29 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf MutableLiveData() } + val isUserScrollingUp = MutableLiveData() + var oneParticipantOneDevice: Boolean = false var addressToCall: Address? = null var onlyParticipantOnlyDeviceAddress: Address? = null + val chatUnreadCountTranslateY = MutableLiveData() + + private val bounceAnimator: ValueAnimator by lazy { + ValueAnimator.ofFloat(AppUtils.getDimension(R.dimen.tabs_fragment_unread_count_bounce_offset), 0f).apply { + addUpdateListener { + val value = it.animatedValue as Float + chatUnreadCountTranslateY.value = value + } + interpolator = LinearInterpolator() + duration = 250 + repeatMode = ValueAnimator.REVERSE + repeatCount = ValueAnimator.INFINITE + } + } + private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() { override fun onContactsUpdated() { Log.i("[Chat Room] Contacts have changed") @@ -202,6 +222,8 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf callInProgress.value = chatRoom.core.callsNb > 0 updateRemotesComposing() + + if (corePreferences.enableAnimations) bounceAnimator.start() } override fun onCleared() { @@ -213,6 +235,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf coreContext.contactsManager.removeListener(contactsUpdatedListener) chatRoom.removeListener(chatRoomListener) chatRoom.core.removeListener(coreListener) + if (corePreferences.enableAnimations) bounceAnimator.end() } fun hideMenu(): Boolean { diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index 397295dec..39c2cb6ed 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -142,8 +142,8 @@ class NotificationsManager(private val context: Context) { } if (currentlyDisplayedChatRoomAddress == room.peerAddress.asStringUriOnly()) { - Log.i("[Notifications Manager] Chat room is currently displayed, do not notify received message & mark it as read") - room.markAsRead() + Log.i("[Notifications Manager] Chat room is currently displayed, do not notify received message") + // Mark as read is now done in the DetailChatRoomFragment return } diff --git a/app/src/main/res/drawable-xhdpi/scroll_to_bottom_default.png b/app/src/main/res/drawable-xhdpi/scroll_to_bottom_default.png new file mode 100644 index 000000000..3be410ae1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/scroll_to_bottom_default.png differ diff --git a/app/src/main/res/drawable/scroll_to_bottom.xml b/app/src/main/res/drawable/scroll_to_bottom.xml new file mode 100644 index 000000000..30ca8234c --- /dev/null +++ b/app/src/main/res/drawable/scroll_to_bottom.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/chat_room_detail_fragment.xml b/app/src/main/res/layout/chat_room_detail_fragment.xml index 431c40baa..89ff8d976 100644 --- a/app/src/main/res/layout/chat_room_detail_fragment.xml +++ b/app/src/main/res/layout/chat_room_detail_fragment.xml @@ -26,6 +26,9 @@ + @@ -297,6 +300,38 @@ android:layout_marginTop="8dp" android:layout_marginRight="8dp" /> + + + + + + + +