Commit db3fe201 authored by robotjini's avatar robotjini

Fixed three issues related to chatroom loading speed:

1.Changed the loading of moderator roles until after the room loads up so it does not block the loading of the ui. There isn't actually anything that uses the moderator roles right now, so i am leaving it to the implementer of that on how to best handle the delayed information. I wanted to make sure the functionality was the same after the changes though rather than just deleting it.

2. recycler_view was adding its adapter in showMessages this was causing the error: "E/RecyclerView: No adapter attached; skipping layout"
This seems to be the cause of a missed update step and ui delay. Code to add adapter was added to setupRecyclerView, which is called in the onViewCreated function.

3. loadActiveMembers function was being called from ChatRoomFragment object and the network / data access was being done in the UI thread. Moved the function call from the end of the function loadMessages to just after the end of said function. Changed the function loadActiveMembers to do most of its work in an I.O. thread and just the view updating in a UI thread.
parent 5ceacaf2
......@@ -117,6 +117,7 @@ class ChatRoomPresenter @Inject constructor(
private var chatRoomId: String? = null
private lateinit var chatRoomType: String
private lateinit var chatRoomName: String
private var chatIsBroadcast: Boolean = false
private var chatRoles = emptyList<ChatRoomRole>()
private val stateChannel = Channel<State>()
......@@ -135,47 +136,73 @@ class ChatRoomPresenter @Inject constructor(
draftKey = "${currentServer}_${LocalRepository.DRAFT_KEY}$roomId"
chatRoomId = roomId
chatRoomType = roomType
chatRoomName = roomName
chatRoles = emptyList()
var canModerate = isOwnerOrMod()
GlobalScope.launch(Dispatchers.IO + strategy.jobs) {
try {
chatRoles = if (roomTypeOf(roomType) !is RoomType.DirectMessage) {
client.chatRoomRoles(roomType = roomTypeOf(roomType), roomName = roomName)
} else {
emptyList()
}
} catch (ex: Exception) {
Timber.e(ex)
chatRoles = emptyList()
} finally {
// User has at least an 'owner' or 'moderator' role.
val canModerate = isOwnerOrMod()
// Can post anyway if has the 'post-readonly' permission on server.
val room = dbManager.getRoom(roomId)
room?.let {
chatIsBroadcast = it.chatRoom.broadcast ?: false
val roomUiModel = roomMapper.map(it, true)
launchUI(strategy) {
view.onRoomUpdated(roomUiModel = roomUiModel.copy(
// Can post anyway if has the 'post-readonly' permission on server.
val room = dbManager.getRoom(roomId)
room?.let {
chatIsBroadcast = it.chatRoom.broadcast ?: false
val roomUiModel = roomMapper.map(it, true)
launchUI(strategy) {
view.onRoomUpdated(roomUiModel = roomUiModel.copy(
broadcast = chatIsBroadcast,
canModerate = canModerate,
writable = roomUiModel.writable || canModerate
))
}
))
}
}
loadMessages(roomId, roomType, clearDataSet = true)
chatRoomMessage?.let { messageHelper.messageIdFromPermalink(it) }
loadMessages(roomId, chatRoomType, clearDataSet = true)
loadActiveMembers(roomId, chatRoomType, filterSelfOut = true)
chatRoomMessage?.let { messageHelper.messageIdFromPermalink(it) }
?.let { messageId ->
val name = messageHelper.roomNameFromPermalink(chatRoomMessage)
citeMessage(
name!!,
messageHelper.roomTypeFromPermalink(chatRoomMessage)!!,
messageId,
true
name!!,
messageHelper.roomTypeFromPermalink(chatRoomMessage)!!,
messageId,
true
)
}
subscribeRoomChanges()
/*FIXME: Get chat role can cause unresponsive problems especially on slower connections
We are updating the room again after the first step so that initial messages
get loaded in and the system appears more responsive. Something should be
done to either fix the load in speed of moderator roles or store the
information locally*/
if (getChatRole()) {
canModerate = isOwnerOrMod()
if (canModerate) {
//FIXME: add this in when moderator page is actually created
//view.updateModeration()
}
}
subscribeRoomChanges()
}
}
private suspend fun getChatRole() : Boolean {
var returnVal = false
try {
if (roomTypeOf(chatRoomType) !is RoomType.DirectMessage) {
chatRoles = withContext(Dispatchers.IO + strategy.jobs) {
client.chatRoomRoles(roomType = roomTypeOf(chatRoomType), roomName = chatRoomName)
}
returnVal = true
} else {
chatRoles = emptyList()
}
} catch (ex: Exception) {
Timber.e(ex)
chatRoles = emptyList()
}
return returnVal
}
private suspend fun subscribeRoomChanges() {
......@@ -209,8 +236,8 @@ class ChatRoomPresenter @Inject constructor(
) {
this.chatRoomId = chatRoomId
this.chatRoomType = chatRoomType
launchUI(strategy) {
view.showLoading()
GlobalScope.launch(Dispatchers.IO + strategy.jobs) {
try {
if (offset == 0L) {
// FIXME - load just 50 messages from DB to speed up. We will reload from Network after that
......@@ -246,8 +273,6 @@ class ChatRoomPresenter @Inject constructor(
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
subscribeTypingStatus()
......@@ -793,13 +818,15 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun loadActiveMembers(
suspend fun loadActiveMembers(
chatRoomId: String,
chatRoomType: String,
offset: Long = 0,
filterSelfOut: Boolean = false
) {
launchUI(strategy) {
val activeUsers = mutableListOf<PeopleSuggestionUiModel>()
withContext(Dispatchers.IO + strategy.jobs) {
try {
val members = retryIO("getMembers($chatRoomId, $chatRoomType, $offset)") {
client.getMembers(chatRoomId, roomTypeOf(chatRoomType), offset, 50).result
......@@ -810,7 +837,6 @@ class ChatRoomPresenter @Inject constructor(
// Take at most the 100 most recent messages distinguished by user. Can return less.
val recentMessages = messagesRepository.getRecentMessages(chatRoomId, 100)
.filterNot { filterSelfOut && it.sender?.username == self }
val activeUsers = mutableListOf<PeopleSuggestionUiModel>()
recentMessages.forEach {
val sender = it.sender
val username = sender?.username ?: ""
......@@ -849,11 +875,13 @@ class ChatRoomPresenter @Inject constructor(
)
})
view.populatePeopleSuggestions(activeUsers)
} catch (e: RocketChatException) {
Timber.e(e)
}
}
launchUI(strategy) {
view.populatePeopleSuggestions(activeUsers)
}
}
fun spotlight(query: String, @AutoCompleteType type: Int, filterSelfOut: Boolean = false) {
......
......@@ -425,25 +425,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
if (recycler_view.adapter == null) {
recycler_view.adapter = adapter
if (dataSet.size >= 30) {
recycler_view.addOnScrollListener(endlessRecyclerViewScrollListener)
}
recycler_view.addOnLayoutChangeListener(layoutChangeListener)
recycler_view.addOnScrollListener(onScrollListener)
// Load just once, on the first page...
presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true)
}
val oldMessagesCount = adapter.itemCount
adapter.appendData(dataSet)
if (oldMessagesCount == 0 && dataSet.isNotEmpty()) {
recycler_view.scrollToPosition(0)
verticalScrollOffset.set(0)
}
presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true)
empty_chat_view.isVisible = adapter.itemCount == 0
dismissEmojiKeyboard()
}
......@@ -465,10 +452,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
setupMessageComposer(roomUiModel)
isBroadcastChannel = roomUiModel.broadcast
isFavorite = roomUiModel.favorite.orFalse()
if (isBroadcastChannel && !roomUiModel.canModerate) {
disableMenu = true
activity?.invalidateOptionsMenu()
}
disableMenu = (roomUiModel.broadcast && !roomUiModel.canModerate)
activity?.invalidateOptionsMenu()
}
}
......@@ -803,7 +788,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
presenter.loadMessages(chatRoomId, chatRoomType, page * 30L)
}
}
recycler_view.adapter = adapter
recycler_view.addOnScrollListener(fabScrollListener)
recycler_view.addOnScrollListener(endlessRecyclerViewScrollListener)
recycler_view.addOnLayoutChangeListener(layoutChangeListener)
recycler_view.addOnScrollListener(onScrollListener)
}
private fun setupFab() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment