mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-19 04:09:03 +00:00
changes to inbox handling
This commit is contained in:
parent
b56c16654b
commit
95fa85c7bb
3 changed files with 68 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue