瀏覽代碼

Merge pull request #2490 from nextcloud/bugfix/2478/fixUserStatusesForConversationList

improve fetching of user statuses in conversation list
Tim Krüger 2 年之前
父節點
當前提交
4658292602

+ 1 - 1
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())

+ 8 - 12
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<ConversationItem.Conv
     private final User user;
     private final Context context;
     private GenericTextHeaderItem header;
-    private final Status status;
     private final ViewThemeUtils viewThemeUtils;
 
 
-    public ConversationItem(Conversation conversation, User user, Context activityContext, Status status, final ViewThemeUtils viewThemeUtils) {
+    public ConversationItem(Conversation conversation, User user, Context activityContext, final ViewThemeUtils viewThemeUtils) {
         this.conversation = conversation;
         this.user = user;
         this.context = activityContext;
-        this.status = status;
         this.viewThemeUtils = viewThemeUtils;
     }
 
     public ConversationItem(Conversation conversation, User user,
-                            Context activityContext, GenericTextHeaderItem genericTextHeaderItem, Status status,
+                            Context activityContext, GenericTextHeaderItem genericTextHeaderItem,
                             final ViewThemeUtils viewThemeUtils) {
-        this(conversation, user, activityContext, status, viewThemeUtils);
+        this(conversation, user, activityContext, viewThemeUtils);
         this.header = genericTextHeaderItem;
     }
 
@@ -97,7 +93,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
     public boolean equals(Object o) {
         if (o instanceof ConversationItem) {
             ConversationItem inItem = (ConversationItem) o;
-            return conversation.equals(inItem.getModel()) && Objects.equals(status, inItem.status);
+            return conversation.equals(inItem.getModel());
         }
         return false;
     }
@@ -109,7 +105,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
     @Override
     public int hashCode() {
         int result = conversation.hashCode();
-        result = 31 * result + (status != null ? status.hashCode() : 0);
+        result = 31 * result;
         return result;
     }
 
@@ -196,13 +192,13 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
             holder.binding.favoriteConversationImageView.setVisibility(View.GONE);
         }
 
-        if (status != null && Conversation.ConversationType.ROOM_SYSTEM != conversation.getType()) {
+        if (conversation.getStatus() != null && Conversation.ConversationType.ROOM_SYSTEM != conversation.getType()) {
             float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, appContext);
 
             holder.binding.userStatusImage.setVisibility(View.VISIBLE);
             holder.binding.userStatusImage.setImageDrawable(new StatusDrawable(
-                status.getStatus(),
-                status.getIcon(),
+                conversation.getStatus(),
+                conversation.getStatusIcon(),
                 size,
                 context.getResources().getColor(R.color.bg_default),
                 appContext));

+ 2 - 5
app/src/main/java/com/nextcloud/talk/api/NcApi.java

@@ -44,7 +44,6 @@ import com.nextcloud.talk.models.json.search.ContactsByNumberOverall;
 import com.nextcloud.talk.models.json.signaling.SignalingOverall;
 import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
 import com.nextcloud.talk.models.json.status.StatusOverall;
-import com.nextcloud.talk.models.json.statuses.StatusesOverall;
 import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
@@ -101,7 +100,8 @@ public interface NcApi {
         Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room
      */
     @GET
-    Observable<RoomsOverall> getRooms(@Header("Authorization") String authorization, @Url String url);
+    Observable<RoomsOverall> 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<StatusesOverall> getUserStatuses(@Header("Authorization") String authorization, @Url String url);
-
 
     @POST
     Observable<GenericOverall> sendReaction(@Header("Authorization") String authorization, @Url String url,

+ 1 - 1
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<RoomsOverall> {
                 override fun onSubscribe(d: Disposable) {

+ 61 - 89
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<String, GenericTextHeaderItem>()
     private var conversationsListBottomDialog: ConversationsListBottomDialog? = null
-    private val userStatuses = HashMap<String?, Status>()
     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()
-        }
-    }
-
-    private fun fetchUserStatusesAndRooms() {
-        ncApi.getUserStatuses(credentials, ApiUtils.getUrlForUserStatuses(currentUser!!.baseUrl))
-            .subscribe(object : Observer<StatusesOverall> {
-                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
-                }
-            })
-    }
+    fun fetchRooms() {
+        val includeStatus = isUserStatusAvailable(userManager.currentUser.blockingGet())
 
-    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())
@@ -556,53 +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,
-                            userStatuses[conversation.name],
-                            viewThemeUtils
-                        )
-                        conversationItems.add(conversationItem)
-                        val conversationItemWithHeader = ConversationItem(
-                            conversation,
-                            currentUser,
-                            activity,
-                            callHeaderItems[headerTitle],
-                            userStatuses[conversation.name],
-                            viewThemeUtils
-                        )
-                        conversationItemsWithHeader.add(conversationItemWithHeader)
-                    }
+                    addToConversationItems(conversation)
                 }
                 sortConversations(conversationItems)
                 sortConversations(conversationItemsWithHeader)
@@ -628,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(
@@ -681,7 +654,6 @@ class ConversationsListController(bundle: Bundle) :
                             currentUser,
                             activity,
                             callHeaderItems[headerTitle],
-                            userStatuses[conversation.name],
                             viewThemeUtils
                         )
                         openConversationItems.add(conversationItem)
@@ -742,7 +714,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 +1154,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 +1163,7 @@ class ConversationsListController(bundle: Bundle) :
 
     @Subscribe(threadMode = ThreadMode.MAIN)
     fun onMessageEvent(conversationsListFetchDataEvent: ConversationsListFetchDataEvent?) {
-        fetchData()
+        fetchRooms()
         Handler().postDelayed({
             if (conversationsListBottomDialog!!.isShowing) {
                 conversationsListBottomDialog!!.dismiss()

+ 13 - 1
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'

+ 0 - 41
app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOCS.kt

@@ -1,41 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Tim Krüger
- * @author Andy Scherzinger
- * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
- * Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-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<Status>?
-) : Parcelable {
-    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
-    constructor() : this(null, null)
-}

+ 0 - 37
app/src/main/java/com/nextcloud/talk/models/json/statuses/StatusesOverall.kt

@@ -1,37 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Tim Krüger
- * @author Andy Scherzinger
- * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
- * Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-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)
-}

+ 1 - 1
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) {