From 871f798720328756f1b6d7bdb4a2fe0f27b1baed Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Thu, 13 Oct 2022 11:54:51 +0200 Subject: [PATCH 1/2] improve fetching of user statuses in conversation list replace /ocs/v2.php/apps/user_status/api/v1/statuses with "includeStatus=true" when fetching conversations, see https://nextcloud-talk.readthedocs.io/en/latest/conversation/ fix #2478 Signed-off-by: Marcel Hibbe --- .../talk/activities/CallActivity.java | 2 +- .../talk/adapters/items/ConversationItem.java | 20 +++---- .../java/com/nextcloud/talk/api/NcApi.java | 7 +-- .../talk/controllers/ChatController.kt | 2 +- .../ConversationsListController.kt | 54 ++++--------------- .../models/json/conversations/Conversation.kt | 14 ++++- .../talk/models/json/statuses/StatusesOCS.kt | 41 -------------- .../models/json/statuses/StatusesOverall.kt | 37 ------------- .../dialog/ConversationsListBottomDialog.kt | 2 +- 9 files changed, 35 insertions(+), 144 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOCS.kt delete mode 100644 app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOverall.kt diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index 4b65a8fb1..c7aad0c37 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -564,7 +564,7 @@ public class CallActivity extends CallBaseActivity { private void handleFromNotification() { int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1}); - ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl)) + ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl), false) .retry(3) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java index 7110277df..fe9febafe 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java @@ -43,7 +43,6 @@ import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding; import com.nextcloud.talk.models.json.chat.ChatMessage; import com.nextcloud.talk.models.json.conversations.Conversation; -import com.nextcloud.talk.models.json.status.Status; import com.nextcloud.talk.ui.StatusDrawable; import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.ApiUtils; @@ -51,7 +50,6 @@ import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew; import java.util.List; -import java.util.Objects; import java.util.regex.Pattern; import androidx.core.content.ContextCompat; @@ -74,22 +72,20 @@ public class ConversationItem extends AbstractFlexibleItem getRooms(@Header("Authorization") String authorization, @Url String url); + Observable getRooms(@Header("Authorization") String authorization, @Url String url, + @Nullable @Query("includeStatus") Boolean includeStatus); /* Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken @@ -518,9 +518,6 @@ public interface NcApi { @Url String url, @Field("statusType") String statusType); - @GET - Observable getUserStatuses(@Header("Authorization") String authorization, @Url String url); - @POST Observable sendReaction(@Header("Authorization") String authorization, @Url String url, diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt index 0a227e5f7..1e55d37dc 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt @@ -423,7 +423,7 @@ class ChatController(args: Bundle) : } Log.d(TAG, "handleFromNotification - getRooms - calling") - ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, conversationUser?.baseUrl)) + ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, conversationUser?.baseUrl), false) ?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread()) ?.subscribe(object : Observer { override fun onSubscribe(d: Disposable) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt index 3c9098054..8e6a0e464 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt @@ -96,20 +96,18 @@ import com.nextcloud.talk.messagesearch.MessageSearchHelper import com.nextcloud.talk.messagesearch.MessageSearchHelper.MessageSearchResults import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.RoomsOverall -import com.nextcloud.talk.models.json.status.Status -import com.nextcloud.talk.models.json.statuses.StatusesOverall import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment import com.nextcloud.talk.ui.dialog.ChooseAccountShareToDialogFragment import com.nextcloud.talk.ui.dialog.ConversationsListBottomDialog import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.ParticipantPermissions import com.nextcloud.talk.utils.ClosedInterfaceImpl import com.nextcloud.talk.utils.ConductorRemapping.remapChatController import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.FileUtils import com.nextcloud.talk.utils.Mimetype +import com.nextcloud.talk.utils.ParticipantPermissions import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ACTIVE_CONVERSATION import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_HIDE_SOURCE_ROOM @@ -131,7 +129,6 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import io.reactivex.Observable -import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers @@ -198,7 +195,6 @@ class ConversationsListController(bundle: Bundle) : private var layoutManager: SmoothScrollLinearLayoutManager? = null private val callHeaderItems = HashMap() private var conversationsListBottomDialog: ConversationsListBottomDialog? = null - private val userStatuses = HashMap() private var searchHelper: MessageSearchHelper? = null private var searchViewDisposable: Disposable? = null @@ -318,7 +314,7 @@ class ConversationsListController(bundle: Bundle) : viewThemeUtils.material .colorMaterialTextButton((activity as MainActivity?)!!.binding.switchAccountButton) } - fetchData() + fetchRooms() } } @@ -493,39 +489,9 @@ class ConversationsListController(bundle: Bundle) : searchItem!!.expandActionView() } - fun fetchData() { - if (isUserStatusAvailable(userManager.currentUser.blockingGet())) { - fetchUserStatusesAndRooms() - } else { - fetchRooms() - } - } + fun fetchRooms() { + val includeStatus = isUserStatusAvailable(userManager.currentUser.blockingGet()) - private fun fetchUserStatusesAndRooms() { - ncApi.getUserStatuses(credentials, ApiUtils.getUrlForUserStatuses(currentUser!!.baseUrl)) - .subscribe(object : Observer { - override fun onSubscribe(d: Disposable) { - // unused atm - } - override fun onNext(statusesOverall: StatusesOverall) { - for (status in statusesOverall.ocs!!.data!!) { - userStatuses[status.userId] = status - } - fetchRooms() - } - - override fun onError(e: Throwable) { - Log.e(TAG, "failed to fetch user statuses", e) - fetchRooms() - } - - override fun onComplete() { - // unused atm - } - }) - } - - private fun fetchRooms() { dispose(null) isRefreshing = true conversationItems = ArrayList() @@ -538,7 +504,8 @@ class ConversationsListController(bundle: Bundle) : ApiUtils.getUrlForRooms( apiVersion, currentUser!!.baseUrl - ) + ), + includeStatus ) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -589,7 +556,6 @@ class ConversationsListController(bundle: Bundle) : conversation, currentUser, activity, - userStatuses[conversation.name], viewThemeUtils ) conversationItems.add(conversationItem) @@ -598,7 +564,6 @@ class ConversationsListController(bundle: Bundle) : currentUser, activity, callHeaderItems[headerTitle], - userStatuses[conversation.name], viewThemeUtils ) conversationItemsWithHeader.add(conversationItemWithHeader) @@ -681,7 +646,6 @@ class ConversationsListController(bundle: Bundle) : currentUser, activity, callHeaderItems[headerTitle], - userStatuses[conversation.name], viewThemeUtils ) openConversationItems.add(conversationItem) @@ -742,7 +706,7 @@ class ConversationsListController(bundle: Bundle) : } false } - binding.swipeRefreshLayoutView.setOnRefreshListener { fetchData() } + binding.swipeRefreshLayoutView.setOnRefreshListener { fetchRooms() } viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshLayoutView) binding.emptyLayout.setOnClickListener { showNewConversationsScreen() } binding.floatingActionButton.setOnClickListener { @@ -1182,7 +1146,7 @@ class ConversationsListController(bundle: Bundle) : if (currentUser != null && eventStatus.userId == currentUser!!.id) { when (eventStatus.eventType) { EventStatus.EventType.CONVERSATION_UPDATE -> if (eventStatus.isAllGood && !isRefreshing) { - fetchData() + fetchRooms() } else -> {} } @@ -1191,7 +1155,7 @@ class ConversationsListController(bundle: Bundle) : @Subscribe(threadMode = ThreadMode.MAIN) fun onMessageEvent(conversationsListFetchDataEvent: ConversationsListFetchDataEvent?) { - fetchData() + fetchRooms() Handler().postDelayed({ if (conversationsListBottomDialog!!.isShowing) { conversationsListBottomDialog!!.dismiss() diff --git a/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt b/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt index 0160f649c..4fa6a111f 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt +++ b/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt @@ -127,7 +127,19 @@ data class Conversation( var permissions: Int = 0, @JsonField(name = ["messageExpiration"]) - var messageExpiration: Int = 0 + var messageExpiration: Int = 0, + + @JsonField(name = ["status"]) + var status: String? = null, + + @JsonField(name = ["statusIcon"]) + var statusIcon: String? = null, + + @JsonField(name = ["statusMessage"]) + var statusMessage: String? = null, + + @JsonField(name = ["statusClearAt"]) + var statusClearAt: Long? = 0 ) : Parcelable { // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' diff --git a/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOCS.kt b/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOCS.kt deleted file mode 100644 index 95937fff4..000000000 --- a/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOCS.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Tim Krüger - * @author Andy Scherzinger - * Copyright (C) 2022 Andy Scherzinger - * Copyright (C) 2021 Tim Krüger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.nextcloud.talk.models.json.statuses - -import android.os.Parcelable -import com.bluelinelabs.logansquare.annotation.JsonField -import com.bluelinelabs.logansquare.annotation.JsonObject -import com.nextcloud.talk.models.json.generic.GenericMeta -import com.nextcloud.talk.models.json.status.Status -import kotlinx.android.parcel.Parcelize - -@Parcelize -@JsonObject -data class StatusesOCS( - @JsonField(name = ["meta"]) - var meta: GenericMeta?, - @JsonField(name = ["data"]) - var data: List? -) : Parcelable { - // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' - constructor() : this(null, null) -} diff --git a/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOverall.kt b/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOverall.kt deleted file mode 100644 index 0a65abac1..000000000 --- a/app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOverall.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Tim Krüger - * @author Andy Scherzinger - * Copyright (C) 2022 Andy Scherzinger - * Copyright (C) 2021 Tim Krüger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.nextcloud.talk.models.json.statuses - -import android.os.Parcelable -import com.bluelinelabs.logansquare.annotation.JsonField -import com.bluelinelabs.logansquare.annotation.JsonObject -import kotlinx.android.parcel.Parcelize - -@Parcelize -@JsonObject -data class StatusesOverall( - @JsonField(name = ["ocs"]) - var ocs: StatusesOCS? -) : Parcelable { - // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' - constructor() : this(null) -} diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt index d9a16aceb..8dd0caf72 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt @@ -202,7 +202,7 @@ class ConversationsListBottomDialog( .popChangeHandler(HorizontalChangeHandler()) ) - controller.fetchData() + controller.fetchRooms() } private fun executeEntryMenuController(operation: ConversationOperationEnum) { From 42e6d9b52fa0862d2f1c35646c3235cd0dd0bc80 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Thu, 13 Oct 2022 13:26:31 +0200 Subject: [PATCH 2/2] extract methods from fetchRooms method reduce complexity for codacy score.. Signed-off-by: Marcel Hibbe --- .../ConversationsListController.kt | 96 ++++++++++--------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt index 8e6a0e464..680ca6f93 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt @@ -523,51 +523,9 @@ class ConversationsListController(bundle: Bundle) : adapterWasNull = false binding.loadingContent.visibility = View.GONE } - if (ocs!!.data!!.isNotEmpty()) { - if (binding.emptyLayout.visibility != View.GONE) { - binding.emptyLayout.visibility = View.GONE - } - if (binding.swipeRefreshLayoutView.visibility != View.VISIBLE) { - binding.swipeRefreshLayoutView.visibility = View.VISIBLE - } - } else { - if (binding.emptyLayout.visibility != View.VISIBLE) { - binding.emptyLayout.visibility = View.VISIBLE - } - if (binding.swipeRefreshLayoutView.visibility != View.GONE) { - binding.swipeRefreshLayoutView.visibility = View.GONE - } - } + initOverallLayout(ocs!!.data!!.isNotEmpty()) for (conversation in ocs.data!!) { - if (bundle.containsKey(KEY_FORWARD_HIDE_SOURCE_ROOM) && conversation.roomId == bundle.getString( - KEY_FORWARD_HIDE_SOURCE_ROOM - ) - ) { - continue - } - val headerTitle: String = resources!!.getString(R.string.conversations) - var genericTextHeaderItem: GenericTextHeaderItem - if (!callHeaderItems.containsKey(headerTitle)) { - genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils) - callHeaderItems[headerTitle] = genericTextHeaderItem - } - if (activity != null) { - val conversationItem = ConversationItem( - conversation, - currentUser, - activity, - viewThemeUtils - ) - conversationItems.add(conversationItem) - val conversationItemWithHeader = ConversationItem( - conversation, - currentUser, - activity, - callHeaderItems[headerTitle], - viewThemeUtils - ) - conversationItemsWithHeader.add(conversationItemWithHeader) - } + addToConversationItems(conversation) } sortConversations(conversationItems) sortConversations(conversationItemsWithHeader) @@ -593,6 +551,56 @@ class ConversationsListController(bundle: Bundle) : } } + private fun initOverallLayout(isConversationListNotEmpty: Boolean) { + if (isConversationListNotEmpty) { + if (binding.emptyLayout.visibility != View.GONE) { + binding.emptyLayout.visibility = View.GONE + } + if (binding.swipeRefreshLayoutView.visibility != View.VISIBLE) { + binding.swipeRefreshLayoutView.visibility = View.VISIBLE + } + } else { + if (binding.emptyLayout.visibility != View.VISIBLE) { + binding.emptyLayout.visibility = View.VISIBLE + } + if (binding.swipeRefreshLayoutView.visibility != View.GONE) { + binding.swipeRefreshLayoutView.visibility = View.GONE + } + } + } + + private fun addToConversationItems(conversation: Conversation) { + if (bundle.containsKey(KEY_FORWARD_HIDE_SOURCE_ROOM) && conversation.roomId == bundle.getString( + KEY_FORWARD_HIDE_SOURCE_ROOM + ) + ) { + return + } + val headerTitle: String = resources!!.getString(R.string.conversations) + val genericTextHeaderItem: GenericTextHeaderItem + if (!callHeaderItems.containsKey(headerTitle)) { + genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils) + callHeaderItems[headerTitle] = genericTextHeaderItem + } + if (activity != null) { + val conversationItem = ConversationItem( + conversation, + currentUser, + activity, + viewThemeUtils + ) + conversationItems.add(conversationItem) + val conversationItemWithHeader = ConversationItem( + conversation, + currentUser, + activity, + callHeaderItems[headerTitle], + viewThemeUtils + ) + conversationItemsWithHeader.add(conversationItemWithHeader) + } + } + private fun showErrorDialog() { val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) .setIcon(