From 95fa85c7bbae8386aead7d7f3340f3879a6797cf Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 15 Apr 2020 15:05:21 +0200 Subject: [PATCH] changes to inbox handling --- .../social/InboxMessageListFragment.kt | 11 +++- .../fragments/social/InboxOverviewFragment.kt | 2 +- .../habitica/ui/viewmodels/InboxViewModel.kt | 66 +++++++++++++++++-- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt index 0ddcc3387..444e2c706 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt @@ -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 diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxOverviewFragment.kt index 21ba46114..78914f2ff 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxOverviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxOverviewFragment.kt @@ -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() } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt index ba16da99d..9a893bd70 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt @@ -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> = dataSourceFactory.toLiveData(config) + private val member: MutableLiveData by lazy { + MutableLiveData() + } + fun getMemberData(): LiveData = 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>() + 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() { private var lastFetchWasEnd = false override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback) { @@ -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() { val sourceLiveData = MutableLiveData() var latestSource: MessagesDataSource = MessagesDataSource(socialRepository, recipientID) + + fun updateRecipientID(newID: String?) { + recipientID = newID + latestSource.recipientID = newID + } + override fun create(): DataSource { 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 create(modelClass: Class): T { - return InboxViewModel(recipientID) as T + return InboxViewModel(recipientID, recipientUsername) as T } } \ No newline at end of file