fix: race condition when loading into a dm channel on startup
This commit is contained in:
parent
d3d802df12
commit
f93c22ee14
|
|
@ -429,79 +429,78 @@ class ChannelScreenViewModel(
|
||||||
ignoreExisting: Boolean = false,
|
ignoreExisting: Boolean = false,
|
||||||
markLastAsRead: Boolean = false
|
markLastAsRead: Boolean = false
|
||||||
) {
|
) {
|
||||||
channel?.id?.let { channelId ->
|
val currentChannelId = channelId ?: return
|
||||||
loadMessagesJob = viewModelScope.launch {
|
loadMessagesJob = viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
val messages = arrayListOf<Message>()
|
val messages = arrayListOf<Message>()
|
||||||
|
|
||||||
fetchMessagesFromChannel(channelId, amount, true, before, after, around).let {
|
fetchMessagesFromChannel(currentChannelId, amount, true, before, after, around).let {
|
||||||
if (it.messages.isNullOrEmpty() || it.messages!!.size < 50) {
|
if (it.messages.isNullOrEmpty() || it.messages!!.size < 50) {
|
||||||
endOfChannel = true
|
endOfChannel = true
|
||||||
}
|
}
|
||||||
|
|
||||||
it.users?.forEach { user ->
|
it.users?.forEach { user ->
|
||||||
if (!StoatAPI.userCache.containsKey(user.id)) {
|
if (!StoatAPI.userCache.containsKey(user.id)) {
|
||||||
StoatAPI.userCache[user.id!!] = user
|
StoatAPI.userCache[user.id!!] = user
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it.messages?.forEach { message ->
|
|
||||||
addUserIfUnknown(message.author ?: return@forEach)
|
|
||||||
if (!StoatAPI.messageCache.containsKey(message.id)) {
|
|
||||||
StoatAPI.messageCache[message.id!!] = message
|
|
||||||
}
|
|
||||||
messages.add(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
it.members?.forEach { member ->
|
|
||||||
if (!StoatAPI.members.hasMember(member.id!!.server, member.id!!.user)) {
|
|
||||||
StoatAPI.members.setMember(member.id!!.server, member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (markLastAsRead) {
|
|
||||||
ackMessage(messages.firstOrNull()?.id ?: return@launch)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val newItems = messages.filter {
|
it.messages?.forEach { message ->
|
||||||
if (ignoreExisting) {
|
addUserIfUnknown(message.author ?: return@forEach)
|
||||||
items.none { m ->
|
if (!StoatAPI.messageCache.containsKey(message.id)) {
|
||||||
when (m) {
|
StoatAPI.messageCache[message.id!!] = message
|
||||||
is ChannelScreenItem.RegularMessage -> m.message.id == it.id
|
|
||||||
is ChannelScreenItem.ProspectiveMessage -> m.message.id == it.id
|
|
||||||
is ChannelScreenItem.SystemMessage -> m.message.id == it.id
|
|
||||||
is ChannelScreenItem.FailedMessage -> m.message.id == it.id
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}.map {
|
messages.add(message)
|
||||||
when {
|
}
|
||||||
it.system != null -> ChannelScreenItem.SystemMessage(it)
|
|
||||||
else -> ChannelScreenItem.RegularMessage(it)
|
it.members?.forEach { member ->
|
||||||
|
if (!StoatAPI.members.hasMember(member.id!!.server, member.id!!.user)) {
|
||||||
|
StoatAPI.members.setMember(member.id!!.server, member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place items according to whether above/below/around was specified.
|
if (markLastAsRead) {
|
||||||
// TODO: Aditionally, place LoadTriggers at the beginning and end of the list.
|
ackMessage(messages.firstOrNull()?.id ?: return@launch)
|
||||||
val newItemsWithPosition = when {
|
|
||||||
before != null -> items + newItems
|
|
||||||
after != null -> newItems + items
|
|
||||||
// TODO around, which should place the new items in the middle of the list
|
|
||||||
else -> newItems
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateItems(newItemsWithPosition)
|
|
||||||
|
|
||||||
if (!didInitialChannelFetch) {
|
|
||||||
didInitialChannelFetch = true
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("ChannelScreenViewModel", "Failed to fetch messages", e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val newItems = messages.filter {
|
||||||
|
if (ignoreExisting) {
|
||||||
|
items.none { m ->
|
||||||
|
when (m) {
|
||||||
|
is ChannelScreenItem.RegularMessage -> m.message.id == it.id
|
||||||
|
is ChannelScreenItem.ProspectiveMessage -> m.message.id == it.id
|
||||||
|
is ChannelScreenItem.SystemMessage -> m.message.id == it.id
|
||||||
|
is ChannelScreenItem.FailedMessage -> m.message.id == it.id
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.map {
|
||||||
|
when {
|
||||||
|
it.system != null -> ChannelScreenItem.SystemMessage(it)
|
||||||
|
else -> ChannelScreenItem.RegularMessage(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place items according to whether above/below/around was specified.
|
||||||
|
// TODO: Aditionally, place LoadTriggers at the beginning and end of the list.
|
||||||
|
val newItemsWithPosition = when {
|
||||||
|
before != null -> items + newItems
|
||||||
|
after != null -> newItems + items
|
||||||
|
// TODO around, which should place the new items in the middle of the list
|
||||||
|
else -> newItems
|
||||||
|
}
|
||||||
|
|
||||||
|
updateItems(newItemsWithPosition)
|
||||||
|
|
||||||
|
if (!didInitialChannelFetch) {
|
||||||
|
didInitialChannelFetch = true
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("ChannelScreenViewModel", "Failed to fetch messages", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue