changes to inbox handling

This commit is contained in:
Phillip Thelen 2020-04-15 15:05:21 +02:00
parent b56c16654b
commit 95fa85c7bb
3 changed files with 68 additions and 11 deletions

View file

@ -63,13 +63,16 @@ class InboxMessageListFragment : BaseMainFragment(), androidx.swiperefreshlayout
val args = InboxMessageListFragmentArgs.fromBundle(it)
setReceivingUser(args.username, args.userID)
}
viewModel = ViewModelProviders.of(this, InboxViewModelFactory(replyToUserUUID ?: "")).get(InboxViewModel::class.java)
viewModel = ViewModelProviders.of(this, InboxViewModelFactory(replyToUserUUID, chatRoomUser)).get(InboxViewModel::class.java)
val layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this.getActivity())
recyclerView.layoutManager = layoutManager
chatAdapter = InboxAdapter(user)
viewModel?.messages?.observe(this, Observer { chatAdapter?.submitList(it) })
viewModel?.messages?.observe(this.viewLifecycleOwner, Observer { chatAdapter?.submitList(it) })
viewModel?.getMemberData()?.observe(this.viewLifecycleOwner, Observer {
activity?.binding?.toolbarTitle?.text = it?.profile?.name
})
recyclerView.adapter = chatAdapter
recyclerView.itemAnimator = SafeDefaultItemAnimator()
chatAdapter?.let { adapter ->
@ -119,6 +122,7 @@ class InboxMessageListFragment : BaseMainFragment(), androidx.swiperefreshlayout
}
private fun refreshConversation() {
if (viewModel?.memberID?.isNotBlank() != true) { return }
compositeSubscription.add(this.socialRepository.retrieveInboxMessages(replyToUserUUID ?: "", 0)
.subscribe(Consumer {}, RxErrorHandler.handleEmptyError(), Action {
swipeRefreshLayout?.isRefreshing = false
@ -132,12 +136,13 @@ class InboxMessageListFragment : BaseMainFragment(), androidx.swiperefreshlayout
}
private fun sendMessage(chatText: String) {
replyToUserUUID?.let {userID ->
viewModel?.memberID?.let {userID ->
socialRepository.postPrivateMessage(userID, chatText)
.delay(200, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
recyclerView?.scrollToPosition(0)
viewModel?.invalidateDataSource()
}, { error ->
RxErrorHandler.reportError(error)
chatBarView.message = chatText

View file

@ -82,7 +82,6 @@ class InboxOverviewFragment : BaseMainFragment(), androidx.swiperefreshlayout.wi
private fun openNewMessageDialog() {
assert(this.activity != null)
val binding = DialogChooseMessageRecipientBinding.inflate(layoutInflater)
this.activity?.let { thisActivity ->
val alert = HabiticaAlertDialog(thisActivity)
alert.setTitle(getString(R.string.choose_recipient_title))
@ -109,6 +108,7 @@ class InboxOverviewFragment : BaseMainFragment(), androidx.swiperefreshlayout.wi
thisActivity.dismissKeyboard()
}
alert.setAdditionalContentView(binding.root)
binding.uuidEditText.requestFocus()
alert.show()
}

View file

@ -10,10 +10,17 @@ import androidx.paging.PositionalDataSource
import androidx.paging.toLiveData
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.extensions.Optional
import com.habitrpg.android.habitica.extensions.asOptional
import com.habitrpg.android.habitica.extensions.filterOptionalDoOnEmpty
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.social.ChatMessage
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.subjects.BehaviorSubject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@ -21,7 +28,7 @@ import javax.inject.Inject
import kotlin.math.ceil
class InboxViewModel(recipientID: String) : BaseViewModel() {
class InboxViewModel(recipientID: String?, recipientUsername: String?) : BaseViewModel() {
@Inject
lateinit var socialRepository: SocialRepository
@ -32,6 +39,29 @@ class InboxViewModel(recipientID: String) : BaseViewModel() {
private val dataSourceFactory = MessagesDataSourceFactory(socialRepository, recipientID)
val messages: LiveData<PagedList<ChatMessage>> = dataSourceFactory.toLiveData(config)
private val member: MutableLiveData<Member?> by lazy {
MutableLiveData<Member?>()
}
fun getMemberData(): LiveData<Member?> = member
private fun loadMemberFromLocal() {
disposable.add(memberIDFlowable
.filterOptionalDoOnEmpty { member.value = null }
.flatMap { socialRepository.getMember(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer { member.value = it }, RxErrorHandler.handleEmptyError()))
}
protected var memberIDSubject = BehaviorSubject.create<Optional<String>>()
val memberIDFlowable = memberIDSubject.toFlowable(BackpressureStrategy.BUFFER)
fun setMemberID(groupID: String) {
if (groupID == memberIDSubject.value?.value) return
memberIDSubject.onNext(groupID.asOptional())
}
val memberID: String?
get() = memberIDSubject.value?.value
override fun inject(component: UserComponent) {
component.inject(this)
@ -40,9 +70,23 @@ class InboxViewModel(recipientID: String) : BaseViewModel() {
fun invalidateDataSource() {
dataSourceFactory.sourceLiveData.value?.invalidate()
}
init {
if (recipientID?.isNotBlank() == true) {
setMemberID(recipientID)
loadMemberFromLocal()
} else {
socialRepository.getMemberWithUsername(recipientUsername).subscribe(Consumer {
setMemberID(it.id ?: "")
member.value = it
dataSourceFactory.updateRecipientID(memberIDSubject.value?.value)
invalidateDataSource()
}, RxErrorHandler.handleEmptyError())
}
}
}
private class MessagesDataSource(val socialRepository: SocialRepository, val recipientID: String):
private class MessagesDataSource(val socialRepository: SocialRepository, var recipientID: String?):
PositionalDataSource<ChatMessage>() {
private var lastFetchWasEnd = false
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<ChatMessage>) {
@ -51,8 +95,9 @@ private class MessagesDataSource(val socialRepository: SocialRepository, val rec
return
}
GlobalScope.launch(Dispatchers.Main.immediate) {
if (recipientID?.isNotBlank() != true) { return@launch }
val page = ceil(params.startPosition.toFloat() / params.loadSize.toFloat()).toInt()
socialRepository.retrieveInboxMessages(recipientID, page)
socialRepository.retrieveInboxMessages(recipientID ?: "", page)
.subscribe(Consumer {
if (it.size != 10) lastFetchWasEnd = true
callback.onResult(it)
@ -68,7 +113,8 @@ private class MessagesDataSource(val socialRepository: SocialRepository, val rec
.firstElement()
.flatMapPublisher {
if (it.isEmpty()) {
socialRepository.retrieveInboxMessages(recipientID, 0)
if (recipientID?.isNotBlank() != true) { return@flatMapPublisher Flowable.just(it) }
socialRepository.retrieveInboxMessages(recipientID ?: "", 0)
.doOnNext {
messages -> if (messages.size != 10) lastFetchWasEnd = true
}
@ -83,10 +129,16 @@ private class MessagesDataSource(val socialRepository: SocialRepository, val rec
}
}
private class MessagesDataSourceFactory(val socialRepository: SocialRepository, val recipientID: String) :
private class MessagesDataSourceFactory(val socialRepository: SocialRepository, var recipientID: String?) :
DataSource.Factory<Int, ChatMessage>() {
val sourceLiveData = MutableLiveData<MessagesDataSource>()
var latestSource: MessagesDataSource = MessagesDataSource(socialRepository, recipientID)
fun updateRecipientID(newID: String?) {
recipientID = newID
latestSource.recipientID = newID
}
override fun create(): DataSource<Int, ChatMessage> {
latestSource = MessagesDataSource(socialRepository, recipientID)
sourceLiveData.postValue(latestSource)
@ -94,9 +146,9 @@ private class MessagesDataSourceFactory(val socialRepository: SocialRepository,
}
}
class InboxViewModelFactory(private val recipientID: String) : ViewModelProvider.Factory {
class InboxViewModelFactory(private val recipientID: String?, private val recipientUsername: String?) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return InboxViewModel(recipientID) as T
return InboxViewModel(recipientID, recipientUsername) as T
}
}