浏览代码

Migrate ChatMesage, Conversation and directly linked data classes to kotlin

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Andy Scherzinger 2 年之前
父节点
当前提交
8ed5432045
共有 38 个文件被更改,包括 950 次插入1691 次删除
  1. 1 1
      app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java
  2. 1 1
      app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
  3. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java
  4. 9 9
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt
  5. 7 7
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt
  6. 7 7
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt
  7. 6 6
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt
  8. 14 11
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java
  9. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java
  10. 5 5
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt
  11. 3 3
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt
  12. 5 5
      app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt
  13. 31 31
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
  14. 8 8
      app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt
  15. 6 6
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
  16. 13 11
      app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java
  17. 4 4
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt
  18. 18 18
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt
  19. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
  20. 0 694
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java
  21. 450 0
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt
  22. 0 76
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java
  23. 38 0
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.kt
  24. 0 74
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCSSingleMessage.java
  25. 38 0
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCSSingleMessage.kt
  26. 0 624
      app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java
  27. 191 0
      app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt
  28. 15 14
      app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOverall.kt
  29. 0 35
      app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.java
  30. 42 0
      app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.kt
  31. 0 3
      app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOverall.kt
  32. 4 4
      app/src/main/java/com/nextcloud/talk/ui/bottom/sheet/ProfileBottomSheet.kt
  33. 12 12
      app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt
  34. 2 2
      app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt
  35. 2 2
      app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt
  36. 6 6
      app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt
  37. 2 2
      app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt
  38. 1 1
      app/src/test/java/com/nextcloud/talk/utils/ShareUtilsTest.kt

+ 1 - 1
app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java

@@ -288,7 +288,7 @@ public class CallNotificationActivity extends CallBaseActivity {
                             CapabilitiesUtil.hasSpreedFeatureCapability(userBeingCalled,
                                                                         "conversation-call-flags");
                         if (hasCallFlags) {
-                            if (isInCallWithVideo(currentConversation.callFlag)) {
+                            if (isInCallWithVideo(currentConversation.getCallFlag())) {
                                 binding.incomingCallVoiceOrVideoTextView.setText(
                                     String.format(getResources().getString(R.string.nc_call_video),
                                                   getResources().getString(R.string.nc_app_product_name)));

+ 1 - 1
app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt

@@ -281,7 +281,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
                                 )
                                 remapChatController(
                                     router!!, currentUser.id,
-                                    roomOverall.ocs.data.token, bundle, true
+                                    roomOverall.ocs.data.token!!, bundle, true
                                 )
                             }
 

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java

@@ -165,10 +165,10 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                 ContextCompat.getColor(context,
                                        R.color.colorPrimary));
 
-            if (conversation.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
+            if (conversation.getType() == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
                 holder.binding.dialogUnreadBubble.setChipBackgroundColorResource(R.color.colorPrimary);
                 holder.binding.dialogUnreadBubble.setTextColor(Color.WHITE);
-            } else if (conversation.isUnreadMention()) {
+            } else if (conversation.getUnreadMention()) {
                 if (CapabilitiesUtil.hasSpreedFeatureCapability(userEntity, "direct-mention-flag")) {
                     if (conversation.getUnreadMentionDirect()) {
                         holder.binding.dialogUnreadBubble.setChipBackgroundColorResource(R.color.colorPrimary);
@@ -196,7 +196,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
             holder.binding.dialogUnreadBubble.setVisibility(View.GONE);
         }
 
-        if (conversation.isFavorite()) {
+        if (conversation.getFavorite()) {
             holder.binding.favoriteConversationImageView.setVisibility(View.VISIBLE);
         } else {
             holder.binding.favoriteConversationImageView.setVisibility(View.GONE);
@@ -227,7 +227,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                 String authorDisplayName = "";
                 conversation.getLastMessage().setActiveUser(userEntity);
                 String text;
-                if (conversation.getLastMessage().getMessageType() == ChatMessage.MessageType.REGULAR_TEXT_MESSAGE) {
+                if (conversation.getLastMessage().getCalculateMessageType() == ChatMessage.MessageType.REGULAR_TEXT_MESSAGE) {
                     if (conversation.getLastMessage().getActorId().equals(userEntity.getUserId())) {
                         text = String.format(appContext.getString(R.string.nc_formatted_message_you),
                                              conversation.getLastMessage().getLastMessageDisplayText());

+ 9 - 9
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt

@@ -113,11 +113,11 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
     }
 
     private fun setAvatarAndAuthorOnMessageItem(message: ChatMessage) {
-        val author: String = message.actorDisplayName
+        val author: String = message.actorDisplayName!!
         if (!TextUtils.isEmpty(author)) {
             binding.messageAuthor.text = author
             binding.messageUserAvatar.setOnClickListener {
-                (payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
+                (payload as? ProfileBottomSheet)?.showFor(message.actorId!!, itemView.context)
             }
         } else {
             binding.messageAuthor.setText(R.string.nc_nick_guest)
@@ -180,13 +180,13 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
         if (!message.isDeleted && message.parentMessage != null) {
             val parentChatMessage = message.parentMessage
-            parentChatMessage.activeUser = message.activeUser
-            parentChatMessage.imageUrl?.let {
+            parentChatMessage!!.activeUser = message.activeUser
+            parentChatMessage!!.imageUrl?.let {
                 binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
                 binding.messageQuote.quotedMessageImage.load(it) {
                     addHeader(
                         "Authorization",
-                        ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                        ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                     )
                 }
             } ?: run {
@@ -199,7 +199,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
             binding.messageQuote.quotedMessageAuthor
                 .setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast))
 
-            if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) {
+            if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary)
             } else {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
@@ -213,9 +213,9 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
 
     @SuppressLint("SetJavaScriptEnabled", "ClickableViewAccessibility")
     private fun setLocationDataOnMessageItem(message: ChatMessage) {
-        if (message.messageParameters != null && message.messageParameters.size > 0) {
-            for (key in message.messageParameters.keys) {
-                val individualHashMap: Map<String, String> = message.messageParameters[key]!!
+        if (message.messageParameters != null && message.messageParameters!!.size > 0) {
+            for (key in message.messageParameters!!.keys) {
+                val individualHashMap: Map<String?, String?> = message.messageParameters!![key]!!
                 if (individualHashMap["type"] == "geo-location") {
                     locationLon = individualHashMap["longitude"]
                     locationLat = individualHashMap["latitude"]

+ 7 - 7
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt

@@ -154,7 +154,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
 
     private fun updateDownloadState(message: ChatMessage) {
         // check if download worker is already running
-        val fileId = message.getSelectedIndividualHashMap()["id"]
+        val fileId = message.selectedIndividualHashMap!!["id"]
         val workers = WorkManager.getInstance(context!!).getWorkInfosByTag(fileId!!)
 
         try {
@@ -206,11 +206,11 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
     }
 
     private fun setAvatarAndAuthorOnMessageItem(message: ChatMessage) {
-        val author: String = message.actorDisplayName
+        val author: String = message.actorDisplayName!!
         if (!TextUtils.isEmpty(author)) {
             binding.messageAuthor.text = author
             binding.messageUserAvatar.setOnClickListener {
-                (payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
+                (payload as? ProfileBottomSheet)?.showFor(message.actorId!!, itemView.context)
             }
         } else {
             binding.messageAuthor.setText(R.string.nc_nick_guest)
@@ -281,13 +281,13 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
         if (!message.isDeleted && message.parentMessage != null) {
             val parentChatMessage = message.parentMessage
-            parentChatMessage.activeUser = message.activeUser
-            parentChatMessage.imageUrl?.let {
+            parentChatMessage!!.activeUser = message.activeUser
+            parentChatMessage!!.imageUrl?.let {
                 binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
                 binding.messageQuote.quotedMessageImage.load(it) {
                     addHeader(
                         "Authorization",
-                        ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                        ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                     )
                 }
             } ?: run {
@@ -300,7 +300,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
             binding.messageQuote.quotedMessageAuthor
                 .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
 
-            if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) {
+            if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary)
             } else {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)

+ 7 - 7
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt

@@ -120,7 +120,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
             binding.messageQuote.quotedChatMessageView.visibility = View.GONE
         }
 
-        itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable)
+        itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.replyable)
 
         Reaction().showReactions(message, binding.reactions, binding.messageText.context, false)
         binding.reactions.reactionsEmojiWrapper.setOnClickListener {
@@ -136,7 +136,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
         if (!TextUtils.isEmpty(message.actorDisplayName)) {
             binding.messageAuthor.text = message.actorDisplayName
             binding.messageUserAvatar.setOnClickListener {
-                (payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
+                (payload as? ProfileBottomSheet)?.showFor(message.actorId!!, itemView.context)
             }
         } else {
             binding.messageAuthor.setText(R.string.nc_nick_guest)
@@ -169,13 +169,13 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
 
     private fun processParentMessage(message: ChatMessage) {
         val parentChatMessage = message.parentMessage
-        parentChatMessage.activeUser = message.activeUser
+        parentChatMessage!!.activeUser = message.activeUser
         parentChatMessage.imageUrl?.let {
             binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
             binding.messageQuote.quotedMessageImage.load(it) {
                 addHeader(
                     "Authorization",
-                    ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                    ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                 )
             }
         } ?: run {
@@ -188,7 +188,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
         binding.messageQuote.quotedMessageAuthor
             .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
 
-        if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) {
+        if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
             binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary)
         } else {
             binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
@@ -226,13 +226,13 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
     }
 
     private fun processMessageParameters(
-        messageParameters: HashMap<String, HashMap<String, String>>,
+        messageParameters: HashMap<String?, HashMap<String?, String?>>,
         message: ChatMessage,
         messageString: Spannable
     ): Spannable {
         var messageStringInternal = messageString
         for (key in messageParameters.keys) {
-            val individualHashMap = message.messageParameters[key]
+            val individualHashMap = message.messageParameters!![key]
             if (individualHashMap != null) {
                 if (
                     individualHashMap["type"] == "user" ||

+ 6 - 6
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt

@@ -66,7 +66,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
     override fun onBind(message: ChatMessage) {
         super.onBind(message)
         sharedApplication!!.componentApplication.inject(this)
-        val messageParameters: HashMap<String, HashMap<String, String>>? = message.messageParameters
+        val messageParameters: HashMap<String?, HashMap<String?, String?>>? = message.messageParameters
         var messageString: Spannable = SpannableString(message.text)
         realView.isSelected = false
         binding.messageTime.setTextColor(context!!.resources.getColor(R.color.white60))
@@ -119,7 +119,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
 
         binding.checkMark.setContentDescription(readStatusContentDescriptionString)
 
-        itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable)
+        itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.replyable)
 
         Reaction().showReactions(message, binding.reactions, context!!, true)
         binding.reactions.reactionsEmojiWrapper.setOnClickListener {
@@ -133,13 +133,13 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
 
     private fun processParentMessage(message: ChatMessage) {
         val parentChatMessage = message.parentMessage
-        parentChatMessage.activeUser = message.activeUser
+        parentChatMessage!!.activeUser = message.activeUser
         parentChatMessage.imageUrl?.let {
             binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
             binding.messageQuote.quotedMessageImage.load(it) {
                 addHeader(
                     "Authorization",
-                    ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                    ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                 )
             }
         } ?: run {
@@ -183,13 +183,13 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
     }
 
     private fun processMessageParameters(
-        messageParameters: HashMap<String, HashMap<String, String>>,
+        messageParameters: HashMap<String?, HashMap<String?, String?>>,
         message: ChatMessage,
         messageString: Spannable
     ): Spannable {
         var messageString1 = messageString
         for (key in messageParameters.keys) {
-            val individualHashMap: HashMap<String, String>? = message.messageParameters[key]
+            val individualHashMap: HashMap<String?, String?>? = message.messageParameters!![key]
             if (individualHashMap != null) {
                 if (individualHashMap["type"] == "user" ||
                     individualHashMap["type"] == "guest" ||

+ 14 - 11
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java

@@ -116,8 +116,8 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
     public void onBind(ChatMessage message) {
         super.onBind(message);
         if (userAvatar != null) {
-            if (message.isGrouped || message.isOneToOneConversation) {
-                if (message.isOneToOneConversation) {
+            if (message.isGrouped() || message.isOneToOneConversation()) {
+                if (message.isOneToOneConversation()) {
                     userAvatar.setVisibility(View.GONE);
                 } else {
                     userAvatar.setVisibility(View.INVISIBLE);
@@ -126,11 +126,11 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
                 userAvatar.setVisibility(View.VISIBLE);
                 userAvatar.setOnClickListener(v -> {
                     if (payload instanceof ProfileBottomSheet) {
-                        ((ProfileBottomSheet) payload).showFor(message.actorId, v.getContext());
+                        ((ProfileBottomSheet) payload).showFor(message.getActorId(), v.getContext());
                     }
                 });
 
-                if (ACTOR_TYPE_BOTS.equals(message.actorType) && ACTOR_ID_CHANGELOG.equals(message.actorId)) {
+                if (ACTOR_TYPE_BOTS.equals(message.getActorType()) && ACTOR_ID_CHANGELOG.equals(message.getActorId())) {
                     if (context != null) {
                         Drawable[] layers = new Drawable[2];
                         layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background);
@@ -148,9 +148,9 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
         clickView = getImage();
         getMessageText().setVisibility(View.VISIBLE);
 
-        if (message.getMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
+        if (message.getCalculateMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
 
-            fileViewerUtils = new FileViewerUtils(context, message.activeUser);
+            fileViewerUtils = new FileViewerUtils(context, message.getActiveUser());
 
             String fileName = message.getSelectedIndividualHashMap().get(KEY_NAME);
             getMessageText().setText(fileName);
@@ -177,10 +177,13 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
                 Drawable drawable = ContextCompat.getDrawable(context, drawableResourceId);
                 image.getHierarchy().setPlaceholderImage(drawable);
             } else {
-                fetchFileInformation("/" + message.getSelectedIndividualHashMap().get(KEY_PATH), message.activeUser);
+                fetchFileInformation("/" + message.getSelectedIndividualHashMap().get(KEY_PATH),
+                                     message.getActiveUser());
             }
 
-            if (message.activeUser != null && message.activeUser.getUsername() != null && message.activeUser.getBaseUrl() != null) {
+            if (message.getActiveUser() != null &&
+                message.getActiveUser().getUsername() != null &&
+                message.getActiveUser().getBaseUrl() != null) {
                 clickView.setOnClickListener(v ->
                     fileViewerUtils.openFile(
                         message,
@@ -202,10 +205,10 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
                 message.getSelectedIndividualHashMap().get(MagicPreviewMessageViewHolder.KEY_MIMETYPE),
                 new FileViewerUtils.ProgressUi(progressBar, getMessageText(), image));
 
-        } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) {
+        } else if (message.getCalculateMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) {
             getMessageText().setText("GIPHY");
             DisplayUtils.setClickableString("GIPHY", "https://giphy.com", getMessageText());
-        } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE) {
+        } else if (message.getCalculateMessageType() == ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE) {
             getMessageText().setText("Tenor");
             DisplayUtils.setClickableString("Tenor", "https://tenor.com", getMessageText());
         } else {
@@ -221,7 +224,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
             getMessageText().setText("");
         }
 
-        itemView.setTag(REPLYABLE_VIEW_TAG, message.isReplyable());
+        itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable());
 
         reactionsBinding = getReactionsBinding();
         new Reaction().showReactions(message, reactionsBinding, getMessageText().getContext(), true);

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java

@@ -76,9 +76,9 @@ public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMes
 
         Spannable messageString = new SpannableString(message.getText());
 
-        if (message.messageParameters != null && message.messageParameters.size() > 0) {
-            for (String key : message.messageParameters.keySet()) {
-                Map<String, String> individualMap = message.messageParameters.get(key);
+        if (message.getMessageParameters() != null && message.getMessageParameters().size() > 0) {
+            for (String key : message.getMessageParameters().keySet()) {
+                Map<String, String> individualMap = message.getMessageParameters().get(key);
 
                 if (individualMap != null && individualMap.containsKey("name")) {
                     String searchText;
@@ -97,6 +97,6 @@ public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMes
 
         text.setText(messageString);
 
-        itemView.setTag(REPLYABLE_VIEW_TAG, message.isReplyable());
+        itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable());
     }
 }

+ 5 - 5
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt

@@ -126,9 +126,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
 
     @SuppressLint("SetJavaScriptEnabled", "ClickableViewAccessibility")
     private fun setLocationDataOnMessageItem(message: ChatMessage) {
-        if (message.messageParameters != null && message.messageParameters.size > 0) {
-            for (key in message.messageParameters.keys) {
-                val individualHashMap: Map<String, String> = message.messageParameters[key]!!
+        if (message.messageParameters != null && message.messageParameters!!.size > 0) {
+            for (key in message.messageParameters!!.keys) {
+                val individualHashMap: Map<String?, String?> = message.messageParameters!![key]!!
                 if (individualHashMap["type"] == "geo-location") {
                     locationLon = individualHashMap["longitude"]
                     locationLat = individualHashMap["latitude"]
@@ -185,13 +185,13 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
         if (!message.isDeleted && message.parentMessage != null) {
             val parentChatMessage = message.parentMessage
-            parentChatMessage.activeUser = message.activeUser
+            parentChatMessage!!.activeUser = message.activeUser
             parentChatMessage.imageUrl?.let {
                 binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
                 binding.messageQuote.quotedMessageImage.load(it) {
                     addHeader(
                         "Authorization",
-                        ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                        ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                     )
                 }
             } ?: run {

+ 3 - 3
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt

@@ -180,7 +180,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
 
     private fun updateDownloadState(message: ChatMessage) {
         // check if download worker is already running
-        val fileId = message.getSelectedIndividualHashMap()["id"]
+        val fileId = message.selectedIndividualHashMap!!["id"]
         val workers = WorkManager.getInstance(context!!).getWorkInfosByTag(fileId!!)
 
         try {
@@ -235,13 +235,13 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
         if (!message.isDeleted && message.parentMessage != null) {
             val parentChatMessage = message.parentMessage
-            parentChatMessage.activeUser = message.activeUser
+            parentChatMessage!!.activeUser = message.activeUser
             parentChatMessage.imageUrl?.let {
                 binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
                 binding.messageQuote.quotedMessageImage.load(it) {
                     addHeader(
                         "Authorization",
-                        ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
+                        ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
                     )
                 }
             } ?: run {

+ 5 - 5
app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt

@@ -44,10 +44,10 @@ class Reaction {
         isOutgoingMessage: Boolean
     ) {
         binding.reactionsEmojiWrapper.removeAllViews()
-        if (message.reactions != null && message.reactions.isNotEmpty()) {
+        if (message.reactions != null && message.reactions!!.isNotEmpty()) {
 
             var remainingEmojisToDisplay = MAX_EMOJIS_TO_DISPLAY
-            val showInfoAboutMoreEmojis = message.reactions.size > MAX_EMOJIS_TO_DISPLAY
+            val showInfoAboutMoreEmojis = message.reactions!!.size > MAX_EMOJIS_TO_DISPLAY
 
             val textColor = getTextColor(context, isOutgoingMessage, binding)
             val amountParams = getAmountLayoutParams(context)
@@ -57,7 +57,7 @@ class Reaction {
             val paddingTop = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_TOP, context).toInt()
             val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt()
 
-            for ((emoji, amount) in message.reactions) {
+            for ((emoji, amount) in message.reactions!!) {
                 val emojiWithAmountWrapper = getEmojiWithAmountWrapperLayout(
                     context,
                     message,
@@ -99,8 +99,8 @@ class Reaction {
         emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams
 
         if (message.reactionsSelf != null &&
-            message.reactionsSelf.isNotEmpty() &&
-            message.reactionsSelf.contains(emoji)
+            message.reactionsSelf!!.isNotEmpty() &&
+            message.reactionsSelf!!.contains(emoji)
         ) {
             emojiWithAmountWrapper.background =
                 AppCompatResources.getDrawable(context, R.drawable.reaction_self_background)

+ 31 - 31
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -339,7 +339,7 @@ class ChatController(args: Bundle) :
                         currentConversation = roomOverall.ocs.data
                         Log.d(
                             TAG,
-                            "getRoomInfo. token: " + currentConversation?.getToken() +
+                            "getRoomInfo. token: " + currentConversation?.token +
                                 " sessionId: " + currentConversation?.sessionId
                         )
                         loadAvatarForStatusBar()
@@ -548,7 +548,7 @@ class ChatController(args: Bundle) :
             if (!conversationUser?.userId.equals("?")) {
                 senderId = "users/" + conversationUser?.userId
             } else {
-                senderId = currentConversation?.getActorType() + "/" + currentConversation?.getActorId()
+                senderId = currentConversation?.actorType + "/" + currentConversation?.actorId
             }
 
             Log.d(TAG, "Initialize TalkMessagesListAdapter with senderId: " + senderId)
@@ -579,7 +579,7 @@ class ChatController(args: Bundle) :
         adapter?.registerViewClickListener(
             R.id.playPauseBtn
         ) { view, message ->
-            val filename = message.getSelectedIndividualHashMap()["name"]
+            val filename = message.selectedIndividualHashMap!!["name"]
             val file = File(context!!.cacheDir, filename!!)
             if (file.exists()) {
                 if (message.isPlayingVoiceMessage) {
@@ -934,7 +934,7 @@ class ChatController(args: Bundle) :
         }
 
         if (mediaPlayer == null) {
-            val fileName = message.getSelectedIndividualHashMap()["name"]
+            val fileName = message.selectedIndividualHashMap!!["name"]
             val absolutePath = context!!.cacheDir.absolutePath + "/" + fileName
             mediaPlayer = MediaPlayer().apply {
                 setDataSource(absolutePath)
@@ -978,17 +978,17 @@ class ChatController(args: Bundle) :
         message.isDownloadingVoiceMessage = true
         adapter?.update(message)
 
-        val baseUrl = message.activeUser.baseUrl
-        val userId = message.activeUser.userId
+        val baseUrl = message.activeUser!!.baseUrl
+        val userId = message.activeUser!!.userId
         val attachmentFolder = CapabilitiesUtil.getAttachmentFolder(message.activeUser)
-        val fileName = message.getSelectedIndividualHashMap()["name"]
-        var size = message.getSelectedIndividualHashMap()["size"]
+        val fileName = message.selectedIndividualHashMap!!["name"]
+        var size = message.selectedIndividualHashMap!!["size"]
         if (size == null) {
             size = "-1"
         }
         val fileSize = size.toLong()
-        val fileId = message.getSelectedIndividualHashMap()["id"]
-        val path = message.getSelectedIndividualHashMap()["path"]
+        val fileId = message.selectedIndividualHashMap!!["id"]
+        val path = message.selectedIndividualHashMap!!["path"]
 
         // check if download worker is already running
         val workers = WorkManager.getInstance(
@@ -1223,7 +1223,7 @@ class ChatController(args: Bundle) :
 
     private fun shouldShowLobby(): Boolean {
         if (currentConversation != null) {
-            return currentConversation?.shouldShowLobby(conversationUser) == true
+            return currentConversation?.shouldShowLobby(conversationUser!!) == true
         }
         return false
     }
@@ -1262,7 +1262,7 @@ class ChatController(args: Bundle) :
 
     private fun checkLobbyState() {
         if (currentConversation != null &&
-            currentConversation?.isLobbyViewApplicable(conversationUser) ?: false &&
+            currentConversation?.isLobbyViewApplicable(conversationUser!!) ?: false &&
             isAlive()
         ) {
 
@@ -1270,7 +1270,7 @@ class ChatController(args: Bundle) :
                 getRoomInfo()
             }
 
-            if (currentConversation?.shouldShowLobby(conversationUser) ?: false) {
+            if (currentConversation?.shouldShowLobby(conversationUser!!) ?: false) {
                 binding.lobby.lobbyView.visibility = View.VISIBLE
                 binding.messagesListView.visibility = View.GONE
                 binding.messageInputView.visibility = View.GONE
@@ -2026,7 +2026,7 @@ class ChatController(args: Bundle) :
         }
         pullChatMessagesPending = true
 
-        if (currentConversation != null && currentConversation!!.shouldShowLobby(conversationUser)) {
+        if (currentConversation != null && currentConversation!!.shouldShowLobby(conversationUser!!)) {
             // return
         }
 
@@ -2181,7 +2181,7 @@ class ChatController(args: Bundle) :
         if (response.code() == HTTP_CODE_OK) {
 
             val chatOverall = response.body() as ChatOverall?
-            val chatMessageList = handleSystemMessages(chatOverall?.ocs!!.data)
+            val chatMessageList = handleSystemMessages(chatOverall?.ocs!!.data!!)
 
             if (chatMessageList.isNotEmpty() &&
                 ChatMessage.SystemMessageType.CLEARED_CHAT == chatMessageList[0].systemMessageType
@@ -2455,19 +2455,19 @@ class ChatController(args: Bundle) :
 
             // setDeletionFlagsAndRemoveInfomessages
             if (isInfoMessageAboutDeletion(currentMessage)) {
-                if (!chatMessageMap.containsKey(currentMessage.value.parentMessage.id)) {
+                if (!chatMessageMap.containsKey(currentMessage.value.parentMessage!!.id)) {
                     // if chatMessageMap doesn't contain message to delete (this happens when lookingIntoFuture),
                     // the message to delete has to be modified directly inside the adapter
                     setMessageAsDeleted(currentMessage.value.parentMessage)
                 } else {
-                    chatMessageMap[currentMessage.value.parentMessage.id]!!.isDeleted = true
+                    chatMessageMap[currentMessage.value.parentMessage!!.id]!!.isDeleted = true
                 }
                 chatMessageIterator.remove()
             }
 
             // delete reactions system messages
             else if (isReactionsMessage(currentMessage)) {
-                if (!chatMessageMap.containsKey(currentMessage.value.parentMessage.id)) {
+                if (!chatMessageMap.containsKey(currentMessage.value.parentMessage!!.id)) {
                     updateAdapterForReaction(currentMessage.value.parentMessage)
                 }
 
@@ -2569,7 +2569,7 @@ class ChatController(args: Bundle) :
     }
 
     private fun isSystemMessage(message: ChatMessage): Boolean {
-        return ChatMessage.MessageType.SYSTEM_MESSAGE == message.getMessageType()
+        return ChatMessage.MessageType.SYSTEM_MESSAGE == message.getCalculateMessageType()
     }
 
     fun deleteMessage(message: IMessage?) {
@@ -2603,7 +2603,7 @@ class ChatController(args: Bundle) :
                     }
 
                     override fun onNext(t: ChatOverallSingleMessage) {
-                        if (t.ocs.meta.statusCode == HttpURLConnection.HTTP_ACCEPTED) {
+                        if (t.ocs.meta!!.statusCode == HttpURLConnection.HTTP_ACCEPTED) {
                             Toast.makeText(
                                 context, R.string.nc_delete_message_leaked_to_matterbridge,
                                 Toast.LENGTH_LONG
@@ -2653,15 +2653,15 @@ class ChatController(args: Bundle) :
                 override fun onNext(roomOverall: RoomOverall) {
                     val bundle = Bundle()
                     bundle.putParcelable(KEY_USER_ENTITY, conversationUser)
-                    bundle.putString(KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken())
-                    bundle.putString(KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId())
+                    bundle.putString(KEY_ROOM_TOKEN, roomOverall.getOcs().getData().token)
+                    bundle.putString(KEY_ROOM_ID, roomOverall.getOcs().getData().roomId)
 
                     // FIXME once APIv2+ is used only, the createRoom already returns all the data
                     ncApi!!.getRoom(
                         credentials,
                         ApiUtils.getUrlForRoom(
                             apiVersion, conversationUser?.baseUrl,
-                            roomOverall.getOcs().getData().getToken()
+                            roomOverall.getOcs().getData().token
                         )
                     )
                         .subscribeOn(Schedulers.io())
@@ -2678,7 +2678,7 @@ class ChatController(args: Bundle) :
                                 )
                                 remapChatController(
                                     router, conversationUser!!.id,
-                                    roomOverall.getOcs().getData().getToken(), bundle, true
+                                    roomOverall.getOcs().getData().token!!, bundle, true
                                 )
                             }
 
@@ -2767,9 +2767,9 @@ class ChatController(args: Bundle) :
             message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId &&
             currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL ||
             isShowMessageDeletionButton(message) || // delete
-            ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getMessageType() || // forward
+            ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() || // forward
             message.previousMessageId > NO_PREVIOUS_MESSAGE_ID && // mark as unread
-            ChatMessage.MessageType.SYSTEM_MESSAGE != message.getMessageType() &&
+            ChatMessage.MessageType.SYSTEM_MESSAGE != message.getCalculateMessageType() &&
             BuildConfig.DEBUG
     }
 
@@ -2867,12 +2867,12 @@ class ChatController(args: Bundle) :
             message.reactionsSelf = ArrayList<String>()
         }
 
-        var amount = message.reactions[emoji]
+        var amount = message.reactions!![emoji]
         if (amount == null) {
             amount = 0
         }
-        message.reactions[emoji] = amount + 1
-        message.reactionsSelf.add(emoji)
+        message.reactions!![emoji] = amount + 1
+        message.reactionsSelf!!.add(emoji)
         adapter?.update(message)
     }
 
@@ -2905,7 +2905,7 @@ class ChatController(args: Bundle) :
     override fun hasContentFor(message: ChatMessage, type: Byte): Boolean {
         return when (type) {
             CONTENT_TYPE_LOCATION -> message.hasGeoLocation()
-            CONTENT_TYPE_VOICE_MESSAGE -> message.isVoiceMessage()
+            CONTENT_TYPE_VOICE_MESSAGE -> message.isVoiceMessage
             CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage)
             CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == "-1"
             else -> false
@@ -2980,7 +2980,7 @@ class ChatController(args: Bundle) :
 
                             ConductorRemapping.remapChatController(
                                 router, conversationUser.id,
-                                roomOverall.ocs.data.token, bundle, false
+                                roomOverall.ocs.data.token!!, bundle, false
                             )
                         } else {
                             conversationIntent.putExtras(bundle)

+ 8 - 8
app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt

@@ -263,15 +263,15 @@ class ContactsController(args: Bundle) :
                 override fun onNext(roomOverall: RoomOverall) {
                     val bundle = Bundle()
                     bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser)
-                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken())
-                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId())
+                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().token)
+                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().roomId)
 
                     // FIXME once APIv2 or later is used only, the createRoom already returns all the data
                     ncApi.getRoom(
                         credentials,
                         ApiUtils.getUrlForRoom(
                             apiVersion, currentUser!!.baseUrl,
-                            roomOverall.getOcs().getData().getToken()
+                            roomOverall.getOcs().getData().token
                         )
                     )
                         .subscribeOn(Schedulers.io())
@@ -287,7 +287,7 @@ class ContactsController(args: Bundle) :
                                 )
                                 ConductorRemapping.remapChatController(
                                     router, currentUser!!.id,
-                                    roomOverall.getOcs().getData().getToken(), bundle, true
+                                    roomOverall.getOcs().getData().token!!, bundle, true
                                 )
                             }
 
@@ -752,7 +752,7 @@ class ContactsController(args: Bundle) :
     fun onMessageEvent(openConversationEvent: OpenConversationEvent) {
         ConductorRemapping.remapChatController(
             router, currentUser!!.id,
-            openConversationEvent.conversation!!.getToken(),
+            openConversationEvent.conversation!!.token!!,
             openConversationEvent.bundle!!, true
         )
         contactsBottomDialog?.dismiss()
@@ -827,8 +827,8 @@ class ContactsController(args: Bundle) :
                     if (activity != null) {
                         val bundle = Bundle()
                         bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser)
-                        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken())
-                        bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId())
+                        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().token)
+                        bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().roomId)
                         bundle.putParcelable(
                             BundleKeys.KEY_ACTIVE_CONVERSATION,
                             Parcels.wrap(roomOverall.getOcs().getData())
@@ -836,7 +836,7 @@ class ContactsController(args: Bundle) :
                         ConductorRemapping.remapChatController(
                             router,
                             currentUser!!.id,
-                            roomOverall.getOcs().getData().getToken(),
+                            roomOverall.getOcs().getData().token!!,
                             bundle,
                             true
                         )

+ 6 - 6
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt

@@ -208,7 +208,7 @@ class ConversationInfoController(args: Bundle) :
     private fun setupWebinaryView() {
         if (CapabilitiesUtil.hasSpreedFeatureCapability(conversationUser, "webinary-lobby") &&
             webinaryRoomType(conversation!!) &&
-            conversation!!.canModerate(conversationUser)
+            conversation!!.canModerate(conversationUser!!)
         ) {
             binding.webinarInfoView.webinarSettings.visibility = View.VISIBLE
 
@@ -223,7 +223,7 @@ class ConversationInfoController(args: Bundle) :
                 MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
                     val currentTimeCalendar = Calendar.getInstance()
                     if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
-                        currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * DateConstants.SECOND_DIVIDER
+                        currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer!! * DateConstants.SECOND_DIVIDER
                     }
 
                     dateTimePicker(
@@ -278,7 +278,7 @@ class ConversationInfoController(args: Bundle) :
         ) {
             binding.webinarInfoView.startTimePreferences.setSummary(
                 DateUtils.getLocalDateStringFromTimestampForLobby(
-                    conversation!!.lobbyTimer
+                    conversation!!.lobbyTimer!!
                 )
             )
         } else {
@@ -639,7 +639,7 @@ class ConversationInfoController(args: Bundle) :
 
                             setupWebinaryView()
 
-                            if (!conversation!!.canLeave(conversationUser)) {
+                            if (!conversation!!.canLeave()) {
                                 binding.leaveConversationAction.visibility = View.GONE
                             } else {
                                 binding.leaveConversationAction.visibility = View.VISIBLE
@@ -670,7 +670,7 @@ class ConversationInfoController(args: Bundle) :
 
                             binding.displayNameText.text = conversation!!.displayName
 
-                            if (conversation!!.description != null && !conversation!!.description.isEmpty()) {
+                            if (conversation!!.description != null && !conversation!!.description!!.isEmpty()) {
                                 binding.descriptionText.text = conversation!!.description
                                 binding.conversationDescription.visibility = View.VISIBLE
                             }
@@ -979,7 +979,7 @@ class ConversationInfoController(args: Bundle) :
     }
 
     override fun onItemClick(view: View?, position: Int): Boolean {
-        if (!conversation!!.canModerate(conversationUser)) {
+        if (!conversation!!.canModerate(conversationUser!!)) {
             return true
         }
 

+ 13 - 11
app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java

@@ -561,8 +561,10 @@ public class ConversationsListController extends BaseController implements Searc
                 }
 
                 for (Conversation conversation : roomsOverall.getOcs().getData()) {
-                    if (bundle.containsKey(BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()) && conversation.roomId.equals(bundle.getString(
-                        BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()))) {
+                    if (bundle.containsKey(BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()) &&
+                        conversation.getRoomId().equals(bundle.getString(
+                            BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()))
+                    ) {
                         continue;
                     }
 
@@ -581,7 +583,7 @@ public class ConversationsListController extends BaseController implements Searc
                             conversation,
                             currentUser,
                             getActivity(),
-                            userStatuses.get(conversation.name));
+                            userStatuses.get(conversation.getName()));
                         conversationItems.add(conversationItem);
 
                         ConversationItem conversationItemWithHeader = new ConversationItem(
@@ -589,7 +591,7 @@ public class ConversationsListController extends BaseController implements Searc
                             currentUser,
                             getActivity(),
                             callHeaderItems.get(headerTitle),
-                            userStatuses.get(conversation.name));
+                            userStatuses.get(conversation.getName()));
                         conversationItemsWithHeader.add(conversationItemWithHeader);
                     }
                 }
@@ -628,7 +630,7 @@ public class ConversationsListController extends BaseController implements Searc
             Conversation conversation1 = ((ConversationItem) o1).getModel();
             Conversation conversation2 = ((ConversationItem) o2).getModel();
             return new CompareToBuilder()
-                .append(conversation2.isFavorite(), conversation1.isFavorite())
+                .append(conversation2.getFavorite(), conversation1.getFavorite())
                 .append(conversation2.getLastActivity(), conversation1.getLastActivity())
                 .toComparison();
         });
@@ -662,7 +664,7 @@ public class ConversationsListController extends BaseController implements Searc
                             currentUser,
                             getActivity(),
                             callHeaderItems.get(headerTitle),
-                            userStatuses.get(conversation.name));
+                            userStatuses.get(conversation.getName()));
 
                         openConversationItems.add(conversationItem);
                     }
@@ -770,9 +772,9 @@ public class ConversationsListController extends BaseController implements Searc
             for (AbstractFlexibleItem flexItem : conversationItems) {
                 Conversation conversationItem = ((ConversationItem) flexItem).getModel();
                 int position = adapter.getGlobalPositionOf(flexItem);
-                if ((conversationItem.unreadMention ||
-                    (conversationItem.unreadMessages > 0 &&
-                        conversationItem.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)) &&
+                if ((conversationItem.getUnreadMention() ||
+                    (conversationItem.getUnreadMessages() > 0 &&
+                        conversationItem.getType() == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)) &&
                     position > lastVisibleItem) {
                     nextUnreadConversationScrollPosition = position;
                     if (!newMentionPopupBubble.isShown()) {
@@ -874,7 +876,7 @@ public class ConversationsListController extends BaseController implements Searc
 
             if (selectedConversation != null && getActivity() != null) {
                 boolean hasChatPermission =
-                    new AttendeePermissionsUtil(selectedConversation.permissions).hasChatPermission(currentUser);
+                    new AttendeePermissionsUtil(selectedConversation.getPermissions()).hasChatPermission(currentUser);
 
                 if (showShareToScreen) {
                     if (hasChatPermission && !isReadOnlyConversation(selectedConversation)) {
@@ -902,7 +904,7 @@ public class ConversationsListController extends BaseController implements Searc
     }
 
     private Boolean isReadOnlyConversation(Conversation conversation) {
-        return conversation.conversationReadOnlyState ==
+        return conversation.getConversationReadOnlyState() ==
             Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY;
     }
 

+ 4 - 4
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt

@@ -103,7 +103,7 @@ class EntryMenuController(args: Bundle) :
         super.onViewBound(view)
 
         if (conversation != null && operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) {
-            binding.textEdit.setText(conversation!!.getName())
+            binding.textEdit.setText(conversation!!.name)
         }
 
         binding.textEdit.setOnEditorActionListener { v, actionId, event ->
@@ -127,7 +127,7 @@ class EntryMenuController(args: Bundle) :
             override fun afterTextChanged(s: Editable) {
                 if (!TextUtils.isEmpty(s)) {
                     if (operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) {
-                        if (conversation!!.getName() == null || !conversation!!.getName().equals(s.toString())) {
+                        if (conversation!!.name == null || !conversation!!.name.equals(s.toString())) {
                             if (!binding.okButton.isEnabled) {
                                 binding.okButton.isEnabled = true
                                 binding.okButton.alpha = OPACITY_ENABLED
@@ -260,9 +260,9 @@ class EntryMenuController(args: Bundle) :
             if (operation === ConversationOperationEnum.OPS_CODE_CHANGE_PASSWORD ||
                 operation === ConversationOperationEnum.OPS_CODE_SET_PASSWORD
             ) {
-                conversation!!.setPassword(binding.textEdit.text.toString())
+                conversation!!.password = binding.textEdit.text.toString()
             } else {
-                conversation!!.setName(binding.textEdit.text.toString())
+                conversation!!.name = binding.textEdit.text.toString()
             }
             bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap<Any>(conversation))
             bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation)

+ 18 - 18
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt

@@ -257,9 +257,9 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
             ApiUtils.getUrlForSetChatReadMarker(
                 chatApiVersion(),
                 currentUser!!.baseUrl,
-                conversation!!.getToken()
+                conversation!!.token
             ),
-            conversation!!.lastMessage.jsonMessageId
+            conversation!!.lastMessage!!.jsonMessageId
         )
             .subscribeOn(Schedulers.io())
             .observeOn(AndroidSchedulers.mainThread())
@@ -273,7 +273,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
             ApiUtils.getUrlForRoomPublic(
                 apiVersion(),
                 currentUser!!.baseUrl,
-                conversation!!.getToken()
+                conversation!!.token
             )
         )
             .subscribeOn(Schedulers.io())
@@ -284,15 +284,15 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
 
     private fun operationChangePassword() {
         var pass: String? = ""
-        if (conversation!!.getPassword() != null) {
-            pass = conversation!!.getPassword()
+        if (conversation!!.password != null) {
+            pass = conversation!!.password
         }
         ncApi.setPassword(
             credentials,
             ApiUtils.getUrlForRoomPassword(
                 apiVersion(),
                 currentUser!!.baseUrl,
-                conversation!!.getToken()
+                conversation!!.token
             ),
             pass
         )
@@ -308,7 +308,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
             ApiUtils.getUrlForRoomPublic(
                 apiVersion(),
                 currentUser!!.baseUrl,
-                conversation!!.getToken()
+                conversation!!.token
             )
         )
             .subscribeOn(Schedulers.io())
@@ -323,9 +323,9 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
             ApiUtils.getUrlForRoom(
                 apiVersion(),
                 currentUser!!.baseUrl,
-                conversation!!.getToken()
+                conversation!!.token
             ),
-            conversation!!.getName()
+            conversation!!.name
         )
             .subscribeOn(Schedulers.io())
             .observeOn(AndroidSchedulers.mainThread())
@@ -342,7 +342,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
                 ApiUtils.getUrlForRoomFavorite(
                     apiVersion,
                     currentUser!!.baseUrl,
-                    conversation!!.getToken()
+                    conversation!!.token
                 )
             )
                 .subscribeOn(Schedulers.io())
@@ -355,7 +355,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
                 ApiUtils.getUrlForRoomFavorite(
                     apiVersion,
                     currentUser!!.baseUrl,
-                    conversation!!.getToken()
+                    conversation!!.token
                 )
             )
                 .subscribeOn(Schedulers.io())
@@ -406,7 +406,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
                         credentials,
                         ApiUtils.getUrlForRoom(
                             apiVersion, currentUser!!.baseUrl,
-                            conversation!!.getToken()
+                            conversation!!.token
                         )
                     )
                         .subscribeOn(Schedulers.io())
@@ -461,7 +461,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
 
                 override fun onNext(roomOverall: RoomOverall) {
                     conversation = roomOverall.getOcs().getData()
-                    if (conversation!!.isHasPassword && conversation!!.isGuest) {
+                    if (conversation!!.hasPassword && conversation!!.isGuest) {
                         eventBus.post(ConversationsListFetchDataEvent())
                         val bundle = Bundle()
                         bundle.putParcelable(KEY_ROOM, Parcels.wrap(conversation))
@@ -639,7 +639,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
             retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(
                 apiVersion,
                 currentUser!!.baseUrl,
-                conversation!!.getToken(),
+                conversation!!.token,
                 userId
             )
             ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
@@ -683,7 +683,7 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
                 retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipantWithSource(
                     apiVersion,
                     currentUser!!.baseUrl,
-                    conversation!!.getToken(),
+                    conversation!!.token,
                     "groups",
                     groupId
                 )
@@ -718,9 +718,9 @@ class OperationsMenuController(args: Bundle) : NewBaseController(
     private fun initiateConversation() {
         eventBus.post(ConversationsListFetchDataEvent())
         val bundle = Bundle()
-        bundle.putString(KEY_ROOM_TOKEN, conversation!!.getToken())
-        bundle.putString(KEY_ROOM_ID, conversation!!.getRoomId())
-        bundle.putString(KEY_CONVERSATION_NAME, conversation!!.getDisplayName())
+        bundle.putString(KEY_ROOM_TOKEN, conversation!!.token)
+        bundle.putString(KEY_ROOM_ID, conversation!!.roomId)
+        bundle.putString(KEY_CONVERSATION_NAME, conversation!!.displayName)
         bundle.putParcelable(KEY_USER_ENTITY, currentUser)
         bundle.putParcelable(KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation))
         bundle.putString(KEY_CONVERSATION_PASSWORD, callPassword)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java

@@ -170,7 +170,7 @@ public class NotificationWorker extends Worker {
                             }
                         }
 
-                        muteCall = !(conversation.notificationCalls == 1);
+                        muteCall = !(conversation.getNotificationCalls() == 1);
                     }
 
                     @Override

+ 0 - 694
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java

@@ -1,694 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Tim Krüger
- * Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
- * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
- *
- * 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.chat;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.bluelinelabs.logansquare.annotation.JsonField;
-import com.bluelinelabs.logansquare.annotation.JsonIgnore;
-import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.R;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.converters.EnumSystemMessageTypeConverter;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.stfalcon.chatkit.commons.models.IUser;
-import com.stfalcon.chatkit.commons.models.MessageContentType;
-
-import org.parceler.Parcel;
-
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-import androidx.annotation.Nullable;
-import kotlin.text.Charsets;
-
-@Parcel
-@JsonObject
-public class ChatMessage implements MessageContentType, MessageContentType.Image {
-    private static String TAG = "ChatMessage";
-
-    @JsonIgnore
-    public boolean isGrouped;
-    @JsonIgnore
-    public boolean isOneToOneConversation;
-    @JsonIgnore
-    public UserEntity activeUser;
-    @JsonIgnore
-    public Map<String, String> selectedIndividualHashMap;
-    @JsonIgnore
-    public boolean isDeleted;
-    @JsonField(name = "id")
-    public int jsonMessageId;
-    @JsonIgnore
-    public int previousMessageId = -1;
-    @JsonField(name = "token")
-    public String token;
-    // guests or users
-    @JsonField(name = "actorType")
-    public String actorType;
-    @JsonField(name = "actorId")
-    public String actorId;
-    // send when crafting a message
-    @JsonField(name = "actorDisplayName")
-    public String actorDisplayName;
-    @JsonField(name = "timestamp")
-    public long timestamp;
-    // send when crafting a message, max 1000 lines
-    @JsonField(name = "message")
-    public String message;
-    @JsonField(name = "messageParameters")
-    public HashMap<String, HashMap<String, String>> messageParameters;
-    @JsonField(name = "systemMessage", typeConverter = EnumSystemMessageTypeConverter.class)
-    public SystemMessageType systemMessageType;
-    @JsonField(name = "isReplyable")
-    public boolean replyable;
-    @JsonField(name = "parent")
-    public ChatMessage parentMessage;
-    public Enum<ReadStatus> readStatus = ReadStatus.NONE;
-    @JsonField(name = "messageType")
-    public String messageType;
-    @JsonField(name = "reactions")
-    public LinkedHashMap<String, Integer> reactions;
-    @JsonField(name = "reactionsSelf")
-    public ArrayList<String> reactionsSelf;
-
-    public boolean isDownloadingVoiceMessage;
-    public boolean resetVoiceMessage;
-    public boolean isPlayingVoiceMessage;
-    public int voiceMessageDuration;
-    public int voiceMessagePlayedSeconds;
-    public int voiceMessageDownloadProgress;
-
-    @JsonIgnore
-    List<MessageType> messageTypesToIgnore = Arrays.asList(
-        MessageType.REGULAR_TEXT_MESSAGE,
-        MessageType.SYSTEM_MESSAGE,
-        MessageType.SINGLE_LINK_VIDEO_MESSAGE,
-        MessageType.SINGLE_LINK_AUDIO_MESSAGE,
-        MessageType.SINGLE_LINK_MESSAGE,
-        MessageType.SINGLE_NC_GEOLOCATION_MESSAGE,
-        MessageType.VOICE_MESSAGE);
-
-    public boolean hasFileAttachment() {
-        if (messageParameters != null && messageParameters.size() > 0) {
-            for (HashMap.Entry<String, HashMap<String, String>> entry : messageParameters.entrySet()) {
-                Map<String, String> individualHashMap = entry.getValue();
-                if (MessageDigest.isEqual(
-                    Objects.requireNonNull(individualHashMap.get("type")).getBytes(Charsets.UTF_8),
-                    ("file").getBytes(Charsets.UTF_8))) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public boolean hasGeoLocation() {
-        if (messageParameters != null && messageParameters.size() > 0) {
-            for (HashMap.Entry<String, HashMap<String, String>> entry : messageParameters.entrySet()) {
-                Map<String, String> individualHashMap = entry.getValue();
-
-                if (MessageDigest.isEqual(
-                    Objects.requireNonNull(individualHashMap.get("type")).getBytes(Charsets.UTF_8),
-                    ("geo-location").getBytes(Charsets.UTF_8))) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Nullable
-    @Override
-    public String getImageUrl() {
-        if (messageParameters != null && messageParameters.size() > 0) {
-            for (HashMap.Entry<String, HashMap<String, String>> entry : messageParameters.entrySet()) {
-                Map<String, String> individualHashMap = entry.getValue();
-                if (MessageDigest.isEqual(
-                    Objects.requireNonNull(individualHashMap.get("type")).getBytes(Charsets.UTF_8),
-                    ("file").getBytes(Charsets.UTF_8))) {
-
-                    // TODO: this selectedIndividualHashMap stuff needs to be analyzed and most likely be refactored!
-                    //  it just feels wrong to fill this here inside getImageUrl()
-                    selectedIndividualHashMap = individualHashMap;
-                    if (!isVoiceMessage()) {
-                        if (getActiveUser() != null && getActiveUser().getBaseUrl() != null) {
-                            return (ApiUtils.getUrlForFilePreviewWithFileId(
-                                getActiveUser().getBaseUrl(),
-                                individualHashMap.get("id"),
-                                NextcloudTalkApplication.Companion.getSharedApplication().getResources().getDimensionPixelSize(R.dimen.maximum_file_preview_size)));
-                        } else {
-                            Log.e(TAG, "getActiveUser() or getActiveUser().getBaseUrl() were null when trying to " +
-                                "getImageUrl()");
-                        }
-                    }
-                }
-            }
-        }
-
-        if (!messageTypesToIgnore.contains(getMessageType())) {
-            return getMessage().trim();
-        }
-
-        return null;
-    }
-
-    public MessageType getMessageType() {
-        if (!TextUtils.isEmpty(getSystemMessage())) {
-            return MessageType.SYSTEM_MESSAGE;
-        }
-
-        if (isVoiceMessage()) {
-            return MessageType.VOICE_MESSAGE;
-        }
-
-        if (hasFileAttachment()) {
-            return MessageType.SINGLE_NC_ATTACHMENT_MESSAGE;
-        }
-
-        if (hasGeoLocation()) {
-            return MessageType.SINGLE_NC_GEOLOCATION_MESSAGE;
-        }
-
-
-        return MessageType.REGULAR_TEXT_MESSAGE;
-    }
-
-    public Map<String, String> getSelectedIndividualHashMap() {
-        return selectedIndividualHashMap;
-    }
-
-    public void setSelectedIndividualHashMap(Map<String, String> selectedIndividualHashMap) {
-        this.selectedIndividualHashMap = selectedIndividualHashMap;
-    }
-
-    @Override
-    public String getId() {
-        return Integer.toString(jsonMessageId);
-    }
-
-    @Override
-    public String getText() {
-        return ChatUtils.Companion.getParsedMessage(getMessage(), getMessageParameters());
-    }
-
-    public String getLastMessageDisplayText() {
-        if (getMessageType().equals(MessageType.REGULAR_TEXT_MESSAGE) || getMessageType().equals(MessageType.SYSTEM_MESSAGE) || getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
-            return getText();
-        } else {
-            if (MessageType.SINGLE_LINK_GIPHY_MESSAGE == getMessageType()
-                || MessageType.SINGLE_LINK_TENOR_MESSAGE == getMessageType()
-                || MessageType.SINGLE_LINK_GIF_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_gif_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_gif),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            } else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_attachment_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_attachment),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            } else if (MessageType.SINGLE_NC_GEOLOCATION_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_location_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_location),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            } else if (MessageType.VOICE_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_voice_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_voice),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            /*} else if (getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_link_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }*/
-            } else if (MessageType.SINGLE_LINK_AUDIO_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_audio_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_audio),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            } else if (MessageType.SINGLE_LINK_VIDEO_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_video_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_video),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            } else if (MessageType.SINGLE_LINK_IMAGE_MESSAGE == getMessageType()) {
-                if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_image_you));
-                } else {
-                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_image),
-                                          !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
-                }
-            }
-        }
-
-        return "";
-    }
-
-    @Override
-    public IUser getUser() {
-        return new IUser() {
-            @Override
-            public String getId() {
-                return actorType + "/" + actorId;
-            }
-
-            @Override
-            public String getName() {
-                if (!TextUtils.isEmpty(actorDisplayName)) {
-                    return actorDisplayName;
-                }
-
-                return NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
-            }
-
-            @Override
-            public String getAvatar() {
-                if (getActiveUser() == null) {
-                    return null;
-                } else if (getActorType().equals("users")) {
-                    return ApiUtils.getUrlForAvatar(getActiveUser().getBaseUrl(), actorId, true);
-                } else if (getActorType().equals("bridged")) {
-                    return ApiUtils.getUrlForAvatar(getActiveUser().getBaseUrl(), "bridge-bot",
-                                                    true);
-                } else {
-                    String apiId =
-                        NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
-
-                    if (!TextUtils.isEmpty(getActorDisplayName())) {
-                        apiId = getActorDisplayName();
-                    }
-                    return ApiUtils.getUrlForGuestAvatar(getActiveUser().getBaseUrl(), apiId, true);
-                }
-            }
-        };
-    }
-
-    @Override
-    public Date getCreatedAt() {
-        return new Date(timestamp * 1000L);
-    }
-
-    @Override
-    public String getSystemMessage() {
-        return new EnumSystemMessageTypeConverter().convertToString(getSystemMessageType());
-    }
-
-    public boolean isGrouped() {
-        return this.isGrouped;
-    }
-
-    public boolean isOneToOneConversation() {
-        return this.isOneToOneConversation;
-    }
-
-    public UserEntity getActiveUser() {
-        return this.activeUser;
-    }
-
-    public boolean isDeleted() {
-        return this.isDeleted;
-    }
-
-    public int getJsonMessageId() {
-        return this.jsonMessageId;
-    }
-
-    public String getToken() {
-        return this.token;
-    }
-
-    public String getActorType() {
-        return this.actorType;
-    }
-
-    public String getActorId() {
-        return this.actorId;
-    }
-
-    public String getActorDisplayName() {
-        return this.actorDisplayName;
-    }
-
-    public long getTimestamp() {
-        return this.timestamp;
-    }
-
-    public String getMessage() {
-        return this.message;
-    }
-
-    public HashMap<String, HashMap<String, String>> getMessageParameters() {
-        return this.messageParameters;
-    }
-
-    public SystemMessageType getSystemMessageType() {
-        return this.systemMessageType;
-    }
-
-    public boolean isReplyable() {
-        return this.replyable;
-    }
-
-    public ChatMessage getParentMessage() {
-        return this.parentMessage;
-    }
-
-    public Enum<ReadStatus> getReadStatus() {
-        return this.readStatus;
-    }
-
-    public List<MessageType> getMessageTypesToIgnore() {
-        return this.messageTypesToIgnore;
-    }
-
-    public void setGrouped(boolean isGrouped) {
-        this.isGrouped = isGrouped;
-    }
-
-    public void setOneToOneConversation(boolean isOneToOneConversation) {
-        this.isOneToOneConversation = isOneToOneConversation;
-    }
-
-    public void setActiveUser(UserEntity activeUser) {
-        this.activeUser = activeUser;
-    }
-
-    public void setDeleted(boolean isDeleted) {
-        this.isDeleted = isDeleted;
-    }
-
-    public void setJsonMessageId(int jsonMessageId) {
-        this.jsonMessageId = jsonMessageId;
-    }
-
-    public void setToken(String token) {
-        this.token = token;
-    }
-
-    public void setActorType(String actorType) {
-        this.actorType = actorType;
-    }
-
-    public void setActorId(String actorId) {
-        this.actorId = actorId;
-    }
-
-    public void setActorDisplayName(String actorDisplayName) {
-        this.actorDisplayName = actorDisplayName;
-    }
-
-    public void setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public void setMessageParameters(HashMap<String, HashMap<String, String>> messageParameters) {
-        this.messageParameters = messageParameters;
-    }
-
-    public void setSystemMessageType(SystemMessageType systemMessageType) {
-        this.systemMessageType = systemMessageType;
-    }
-
-    public void setReplyable(boolean replyable) {
-        this.replyable = replyable;
-    }
-
-    public void setParentMessage(ChatMessage parentMessage) {
-        this.parentMessage = parentMessage;
-    }
-
-    public void setReadStatus(Enum<ReadStatus> readStatus) {
-        this.readStatus = readStatus;
-    }
-
-    public void setMessageTypesToIgnore(List<MessageType> messageTypesToIgnore) {
-        this.messageTypesToIgnore = messageTypesToIgnore;
-    }
-
-    public void setMessageType(String messageType) {
-        this.messageType = messageType;
-    }
-
-    public boolean equals(final Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof ChatMessage)) {
-            return false;
-        }
-        final ChatMessage other = (ChatMessage) o;
-        if (!other.canEqual((Object) this)) {
-            return false;
-        }
-        if (this.isGrouped() != other.isGrouped()) {
-            return false;
-        }
-        if (this.isOneToOneConversation() != other.isOneToOneConversation()) {
-            return false;
-        }
-        final Object this$activeUser = this.getActiveUser();
-        final Object other$activeUser = other.getActiveUser();
-        if (this$activeUser == null ? other$activeUser != null : !this$activeUser.equals(other$activeUser)) {
-            return false;
-        }
-        final Object this$selectedIndividualHashMap = this.getSelectedIndividualHashMap();
-        final Object other$selectedIndividualHashMap = other.getSelectedIndividualHashMap();
-        if (this$selectedIndividualHashMap == null ? other$selectedIndividualHashMap != null : !this$selectedIndividualHashMap.equals(other$selectedIndividualHashMap)) {
-            return false;
-        }
-        if (this.isDeleted() != other.isDeleted()) {
-            return false;
-        }
-        if (this.getJsonMessageId() != other.getJsonMessageId()) {
-            return false;
-        }
-        final Object this$token = this.getToken();
-        final Object other$token = other.getToken();
-        if (this$token == null ? other$token != null : !this$token.equals(other$token)) {
-            return false;
-        }
-        final Object this$actorType = this.getActorType();
-        final Object other$actorType = other.getActorType();
-        if (this$actorType == null ? other$actorType != null : !this$actorType.equals(other$actorType)) {
-            return false;
-        }
-        final Object this$actorId = this.getActorId();
-        final Object other$actorId = other.getActorId();
-        if (this$actorId == null ? other$actorId != null : !this$actorId.equals(other$actorId)) {
-            return false;
-        }
-        final Object this$actorDisplayName = this.getActorDisplayName();
-        final Object other$actorDisplayName = other.getActorDisplayName();
-        if (this$actorDisplayName == null ? other$actorDisplayName != null : !this$actorDisplayName.equals(other$actorDisplayName)) {
-            return false;
-        }
-        if (this.getTimestamp() != other.getTimestamp()) {
-            return false;
-        }
-        final Object this$message = this.getMessage();
-        final Object other$message = other.getMessage();
-        if (this$message == null ? other$message != null : !this$message.equals(other$message)) {
-            return false;
-        }
-        final Object this$messageParameters = this.getMessageParameters();
-        final Object other$messageParameters = other.getMessageParameters();
-        if (this$messageParameters == null ? other$messageParameters != null : !this$messageParameters.equals(other$messageParameters)) {
-            return false;
-        }
-        final Object this$systemMessageType = this.getSystemMessageType();
-        final Object other$systemMessageType = other.getSystemMessageType();
-        if (this$systemMessageType == null ? other$systemMessageType != null : !this$systemMessageType.equals(other$systemMessageType)) {
-            return false;
-        }
-        if (this.isReplyable() != other.isReplyable()) {
-            return false;
-        }
-        final Object this$parentMessage = this.getParentMessage();
-        final Object other$parentMessage = other.getParentMessage();
-        if (this$parentMessage == null ? other$parentMessage != null : !this$parentMessage.equals(other$parentMessage)) {
-            return false;
-        }
-        final Object this$readStatus = this.getReadStatus();
-        final Object other$readStatus = other.getReadStatus();
-        if (this$readStatus == null ? other$readStatus != null : !this$readStatus.equals(other$readStatus)) {
-            return false;
-        }
-        final Object this$messageTypesToIgnore = this.getMessageTypesToIgnore();
-        final Object other$messageTypesToIgnore = other.getMessageTypesToIgnore();
-
-        return this$messageTypesToIgnore == null ? other$messageTypesToIgnore == null : this$messageTypesToIgnore.equals(other$messageTypesToIgnore);
-    }
-
-    protected boolean canEqual(final Object other) {
-        return other instanceof ChatMessage;
-    }
-
-    public int hashCode() {
-        final int PRIME = 59;
-        int result = 1;
-        result = result * PRIME + (this.isGrouped() ? 79 : 97);
-        result = result * PRIME + (this.isOneToOneConversation() ? 79 : 97);
-        final Object $activeUser = this.getActiveUser();
-        result = result * PRIME + ($activeUser == null ? 43 : $activeUser.hashCode());
-        final Object $selectedIndividualHashMap = this.getSelectedIndividualHashMap();
-        result = result * PRIME + ($selectedIndividualHashMap == null ? 43 : $selectedIndividualHashMap.hashCode());
-        result = result * PRIME + (this.isDeleted() ? 79 : 97);
-        result = result * PRIME + this.getJsonMessageId();
-        final Object $token = this.getToken();
-        result = result * PRIME + ($token == null ? 43 : $token.hashCode());
-        final Object $actorType = this.getActorType();
-        result = result * PRIME + ($actorType == null ? 43 : $actorType.hashCode());
-        final Object $actorId = this.getActorId();
-        result = result * PRIME + ($actorId == null ? 43 : $actorId.hashCode());
-        final Object $actorDisplayName = this.getActorDisplayName();
-        result = result * PRIME + ($actorDisplayName == null ? 43 : $actorDisplayName.hashCode());
-        final long $timestamp = this.getTimestamp();
-        result = result * PRIME + (int) ($timestamp >>> 32 ^ $timestamp);
-        final Object $message = this.getMessage();
-        result = result * PRIME + ($message == null ? 43 : $message.hashCode());
-        final Object $messageParameters = this.getMessageParameters();
-        result = result * PRIME + ($messageParameters == null ? 43 : $messageParameters.hashCode());
-        final Object $systemMessageType = this.getSystemMessageType();
-        result = result * PRIME + ($systemMessageType == null ? 43 : $systemMessageType.hashCode());
-        result = result * PRIME + (this.isReplyable() ? 79 : 97);
-        final Object $parentMessage = this.getParentMessage();
-        result = result * PRIME + ($parentMessage == null ? 43 : $parentMessage.hashCode());
-        final Object $readStatus = this.getReadStatus();
-        result = result * PRIME + ($readStatus == null ? 43 : $readStatus.hashCode());
-        final Object $messageTypesToIgnore = this.getMessageTypesToIgnore();
-        result = result * PRIME + ($messageTypesToIgnore == null ? 43 : $messageTypesToIgnore.hashCode());
-        return result;
-    }
-
-    public String toString() {
-        return "ChatMessage(isGrouped=" + this.isGrouped() + ", isOneToOneConversation=" + this.isOneToOneConversation() + ", activeUser=" + this.getActiveUser() + ", selectedIndividualHashMap=" + this.getSelectedIndividualHashMap() + ", isDeleted=" + this.isDeleted() + ", jsonMessageId=" + this.getJsonMessageId() + ", token=" + this.getToken() + ", actorType=" + this.getActorType() + ", actorId=" + this.getActorId() + ", actorDisplayName=" + this.getActorDisplayName() + ", timestamp=" + this.getTimestamp() + ", message=" + this.getMessage() + ", messageParameters=" + this.getMessageParameters() + ", systemMessageType=" + this.getSystemMessageType() + ", replyable=" + this.isReplyable() + ", parentMessage=" + this.getParentMessage() + ", readStatus=" + this.getReadStatus() + ", messageTypesToIgnore=" + this.getMessageTypesToIgnore() + ")";
-    }
-
-    public boolean isVoiceMessage() {
-        return "voice-message".equals(messageType);
-    }
-
-    public boolean isCommandMessage() {
-        return "command".equals(messageType);
-    }
-
-    public boolean isDeletedCommentMessage() {
-        return "comment_deleted".equals(messageType);
-    }
-
-    public enum MessageType {
-        REGULAR_TEXT_MESSAGE,
-        SYSTEM_MESSAGE,
-        SINGLE_LINK_GIPHY_MESSAGE,
-        SINGLE_LINK_TENOR_MESSAGE,
-        SINGLE_LINK_GIF_MESSAGE,
-        SINGLE_LINK_MESSAGE,
-        SINGLE_LINK_VIDEO_MESSAGE,
-        SINGLE_LINK_IMAGE_MESSAGE,
-        SINGLE_LINK_AUDIO_MESSAGE,
-        SINGLE_NC_ATTACHMENT_MESSAGE,
-        SINGLE_NC_GEOLOCATION_MESSAGE,
-        VOICE_MESSAGE
-    }
-
-    /**
-     * see https://nextcloud-talk.readthedocs.io/en/latest/chat/#system-messages
-     */
-    public enum SystemMessageType {
-        DUMMY,
-        CONVERSATION_CREATED,
-        CONVERSATION_RENAMED,
-        DESCRIPTION_REMOVED,
-        DESCRIPTION_SET,
-        CALL_STARTED,
-        CALL_JOINED,
-        CALL_LEFT,
-        CALL_ENDED,
-        CALL_ENDED_EVERYONE,
-        CALL_MISSED,
-        CALL_TRIED,
-        READ_ONLY_OFF,
-        READ_ONLY,
-        LISTABLE_NONE,
-        LISTABLE_USERS,
-        LISTABLE_ALL,
-        LOBBY_NONE,
-        LOBBY_NON_MODERATORS,
-        LOBBY_OPEN_TO_EVERYONE,
-        GUESTS_ALLOWED,
-        GUESTS_DISALLOWED,
-        PASSWORD_SET,
-        PASSWORD_REMOVED,
-        USER_ADDED,
-        USER_REMOVED,
-        GROUP_ADDED,
-        GROUP_REMOVED,
-        CIRCLE_ADDED,
-        CIRCLE_REMOVED,
-        MODERATOR_PROMOTED,
-        MODERATOR_DEMOTED,
-        GUEST_MODERATOR_PROMOTED,
-        GUEST_MODERATOR_DEMOTED,
-        MESSAGE_DELETED,
-        FILE_SHARED,
-        OBJECT_SHARED,
-        MATTERBRIDGE_CONFIG_ADDED,
-        MATTERBRIDGE_CONFIG_EDITED,
-        MATTERBRIDGE_CONFIG_REMOVED,
-        MATTERBRIDGE_CONFIG_ENABLED,
-        MATTERBRIDGE_CONFIG_DISABLED,
-        CLEARED_CHAT,
-        REACTION,
-        REACTION_DELETED,
-        REACTION_REVOKED
-    }
-}

+ 450 - 0
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt

@@ -0,0 +1,450 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * @author Tim Krüger
+ * Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ *
+ * 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.chat
+
+import android.os.Parcelable
+import android.text.TextUtils
+import android.util.Log
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonIgnore
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.models.json.chat.ChatUtils.Companion.getParsedMessage
+import com.nextcloud.talk.models.json.converters.EnumSystemMessageTypeConverter
+import com.nextcloud.talk.utils.ApiUtils
+import com.stfalcon.chatkit.commons.models.IUser
+import com.stfalcon.chatkit.commons.models.MessageContentType
+import kotlinx.android.parcel.Parcelize
+import java.security.MessageDigest
+import java.util.ArrayList
+import java.util.Arrays
+import java.util.Date
+import java.util.HashMap
+import java.util.LinkedHashMap
+
+@Parcelize
+@JsonObject
+data class ChatMessage(
+    @JsonIgnore
+    var isGrouped: Boolean = false,
+
+    @JsonIgnore
+    var isOneToOneConversation: Boolean = false,
+
+    @JsonIgnore
+    var activeUser: UserEntity? = null,
+
+    @JsonIgnore
+    var selectedIndividualHashMap: Map<String?, String?>? = null,
+
+    @JsonIgnore
+    var isDeleted: Boolean = false,
+
+    @JsonField(name = ["id"])
+    var jsonMessageId: Int = 0,
+
+    @JsonIgnore
+    var previousMessageId: Int = -1,
+
+    @JsonField(name = ["token"])
+    var token: String? = null,
+
+    // guests or users
+    @JsonField(name = ["actorType"])
+    var actorType: String? = null,
+
+    @JsonField(name = ["actorId"])
+    var actorId: String? = null,
+
+    // send when crafting a message
+    @JsonField(name = ["actorDisplayName"])
+    var actorDisplayName: String? = null,
+
+    @JsonField(name = ["timestamp"])
+    var timestamp: Long = 0,
+
+    // send when crafting a message, max 1000 lines
+    @JsonField(name = ["message"])
+    var message: String? = null,
+
+    @JsonField(name = ["messageParameters"])
+    var messageParameters: HashMap<String?, HashMap<String?, String?>>? = null,
+
+    @JsonField(name = ["systemMessage"], typeConverter = EnumSystemMessageTypeConverter::class)
+    var systemMessageType: SystemMessageType? = null,
+
+    @JsonField(name = ["isReplyable"])
+    var replyable: Boolean = false,
+
+    @JsonField(name = ["parent"])
+    var parentMessage: ChatMessage? = null,
+
+    var readStatus: Enum<ReadStatus> = ReadStatus.NONE,
+
+    @JsonField(name = ["messageType"])
+    var messageType: String? = null,
+
+    @JsonField(name = ["reactions"])
+    var reactions: LinkedHashMap<String, Int>? = null,
+
+    @JsonField(name = ["reactionsSelf"])
+    var reactionsSelf: ArrayList<String>? = null,
+
+    var isDownloadingVoiceMessage: Boolean = false,
+
+    var resetVoiceMessage: Boolean = false,
+
+    var isPlayingVoiceMessage: Boolean = false,
+
+    var voiceMessageDuration: Int = 0,
+
+    var voiceMessagePlayedSeconds: Int = 0,
+
+    var voiceMessageDownloadProgress: Int = 0,
+) : Parcelable, MessageContentType, MessageContentType.Image {
+    @JsonIgnore
+    var messageTypesToIgnore = Arrays.asList(
+        MessageType.REGULAR_TEXT_MESSAGE,
+        MessageType.SYSTEM_MESSAGE,
+        MessageType.SINGLE_LINK_VIDEO_MESSAGE,
+        MessageType.SINGLE_LINK_AUDIO_MESSAGE,
+        MessageType.SINGLE_LINK_MESSAGE,
+        MessageType.SINGLE_NC_GEOLOCATION_MESSAGE,
+        MessageType.VOICE_MESSAGE
+    )
+
+    fun hasFileAttachment(): Boolean {
+        if (messageParameters != null && messageParameters!!.size > 0) {
+            for ((_, individualHashMap) in messageParameters!!) {
+                if (MessageDigest.isEqual(
+                        individualHashMap["type"]!!.toByteArray(),
+                        "file".toByteArray()
+                    )
+                ) {
+                    return true
+                }
+            }
+        }
+        return false
+    }
+
+    fun hasGeoLocation(): Boolean {
+        if (messageParameters != null && messageParameters!!.size > 0) {
+            for ((_, individualHashMap) in messageParameters!!) {
+                if (MessageDigest.isEqual(
+                        individualHashMap["type"]!!.toByteArray(),
+                        "geo-location".toByteArray()
+                    )
+                ) {
+                    return true
+                }
+            }
+        }
+        return false
+    }
+
+    override fun getImageUrl(): String? {
+        if (messageParameters != null && messageParameters!!.size > 0) {
+            for ((_, individualHashMap) in messageParameters!!) {
+                if (MessageDigest.isEqual(
+                        individualHashMap["type"]!!.toByteArray(),
+                        "file".toByteArray()
+                    )
+                ) {
+
+                    // TODO: this selectedIndividualHashMap stuff needs to be analyzed and most likely be refactored!
+                    //  it just feels wrong to fill this here inside getImageUrl()
+                    selectedIndividualHashMap = individualHashMap
+                    if (!isVoiceMessage) {
+                        if (activeUser != null && activeUser!!.baseUrl != null) {
+                            return ApiUtils.getUrlForFilePreviewWithFileId(
+                                activeUser!!.baseUrl,
+                                individualHashMap["id"],
+                                sharedApplication!!.resources.getDimensionPixelSize(R.dimen.maximum_file_preview_size)
+                            )
+                        } else {
+                            Log.e(
+                                TAG, "activeUser or activeUser.getBaseUrl() were null when trying to " +
+                                    "getImageUrl()"
+                            )
+                        }
+                    }
+                }
+            }
+        }
+        return if (!messageTypesToIgnore.contains(getCalculateMessageType())) {
+            message!!.trim { it <= ' ' }
+        } else null
+    }
+
+    fun getCalculateMessageType(): MessageType {
+        if (!TextUtils.isEmpty(systemMessage)) {
+            return MessageType.SYSTEM_MESSAGE
+        }
+        if (isVoiceMessage) {
+            return MessageType.VOICE_MESSAGE
+        }
+        if (hasFileAttachment()) {
+            return MessageType.SINGLE_NC_ATTACHMENT_MESSAGE
+        }
+        return if (hasGeoLocation()) {
+            MessageType.SINGLE_NC_GEOLOCATION_MESSAGE
+        } else MessageType.REGULAR_TEXT_MESSAGE
+    }
+
+    override fun getId(): String {
+        return Integer.toString(jsonMessageId)
+    }
+
+    override fun getText(): String {
+        return getParsedMessage(message, messageParameters)!!
+    }
+
+    /*} else if (getCalculateMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
+                if (actorId.equals(activeUser.getUserId())) {
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_link_you));
+                } else {
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
+                            !TextUtils.isEmpty(actorDisplayName) ? actorDisplayName : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
+                }*/
+    val lastMessageDisplayText: String
+        get() {
+            if (getCalculateMessageType() == MessageType.REGULAR_TEXT_MESSAGE ||
+                getCalculateMessageType() == MessageType.SYSTEM_MESSAGE ||
+                getCalculateMessageType() == MessageType.SINGLE_LINK_MESSAGE) {
+                return text
+            } else {
+                if (MessageType.SINGLE_LINK_GIPHY_MESSAGE == getCalculateMessageType() ||
+                    MessageType.SINGLE_LINK_TENOR_MESSAGE == getCalculateMessageType() ||
+                    MessageType.SINGLE_LINK_GIF_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_a_gif_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_a_gif),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                } else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_an_attachment_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_an_attachment),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                } else if (MessageType.SINGLE_NC_GEOLOCATION_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_location_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_location),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                } else if (MessageType.VOICE_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_voice_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_voice),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                    /*} else if (getCalculateMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
+                if (actorId.equals(activeUser.getUserId())) {
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_link_you));
+                } else {
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
+                            !TextUtils.isEmpty(actorDisplayName) ? actorDisplayName : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
+                }*/
+                } else if (MessageType.SINGLE_LINK_AUDIO_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_an_audio_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_an_audio),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                } else if (MessageType.SINGLE_LINK_VIDEO_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_a_video_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_a_video),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                } else if (MessageType.SINGLE_LINK_IMAGE_MESSAGE == getCalculateMessageType()) {
+                    return if (actorId == activeUser!!.userId) {
+                        sharedApplication!!.getString(R.string.nc_sent_an_image_you)
+                    } else {
+                        String.format(
+                            sharedApplication!!.resources.getString(R.string.nc_sent_an_image),
+                            if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(
+                                R.string.nc_guest
+                            )
+                        )
+                    }
+                }
+            }
+            return ""
+        }
+
+    override fun getUser(): IUser {
+        return object : IUser {
+            override fun getId(): String {
+                return "$actorType/$actorId"
+            }
+
+            override fun getName(): String {
+                return if (!TextUtils.isEmpty(actorDisplayName)) {
+                    actorDisplayName!!
+                } else sharedApplication!!.getString(R.string.nc_guest)
+            }
+
+            override fun getAvatar(): String? {
+                return when {
+                    activeUser == null -> {
+                        null
+                    }
+                    actorType == "users" -> {
+                        ApiUtils.getUrlForAvatar(activeUser!!.baseUrl, actorId, true)
+                    }
+                    actorType == "bridged" -> {
+                        ApiUtils.getUrlForAvatar(
+                            activeUser!!.baseUrl, "bridge-bot",
+                            true
+                        )
+                    }
+                    else -> {
+                        var apiId: String? = sharedApplication!!.getString(R.string.nc_guest)
+                        if (!TextUtils.isEmpty(actorDisplayName)) {
+                            apiId = actorDisplayName
+                        }
+                        ApiUtils.getUrlForGuestAvatar(activeUser!!.baseUrl, apiId, true)
+                    }
+                }
+            }
+        }
+    }
+
+    override fun getCreatedAt(): Date {
+        return Date(timestamp * 1000L)
+    }
+
+    override fun getSystemMessage(): String {
+        return EnumSystemMessageTypeConverter().convertToString(systemMessageType)
+    }
+
+    val isVoiceMessage: Boolean
+        get() = "voice-message" == messageType
+    val isCommandMessage: Boolean
+        get() = "command" == messageType
+    val isDeletedCommentMessage: Boolean
+        get() = "comment_deleted" == messageType
+
+    enum class MessageType {
+        REGULAR_TEXT_MESSAGE,
+        SYSTEM_MESSAGE,
+        SINGLE_LINK_GIPHY_MESSAGE,
+        SINGLE_LINK_TENOR_MESSAGE,
+        SINGLE_LINK_GIF_MESSAGE,
+        SINGLE_LINK_MESSAGE,
+        SINGLE_LINK_VIDEO_MESSAGE,
+        SINGLE_LINK_IMAGE_MESSAGE,
+        SINGLE_LINK_AUDIO_MESSAGE,
+        SINGLE_NC_ATTACHMENT_MESSAGE,
+        SINGLE_NC_GEOLOCATION_MESSAGE,
+        VOICE_MESSAGE
+    }
+
+    /**
+     * see https://nextcloud-talk.readthedocs.io/en/latest/chat/#system-messages
+     */
+    enum class SystemMessageType {
+        DUMMY, CONVERSATION_CREATED,
+        CONVERSATION_RENAMED,
+        DESCRIPTION_REMOVED,
+        DESCRIPTION_SET,
+        CALL_STARTED,
+        CALL_JOINED,
+        CALL_LEFT,
+        CALL_ENDED,
+        CALL_ENDED_EVERYONE,
+        CALL_MISSED,
+        CALL_TRIED,
+        READ_ONLY_OFF,
+        READ_ONLY,
+        LISTABLE_NONE,
+        LISTABLE_USERS,
+        LISTABLE_ALL,
+        LOBBY_NONE,
+        LOBBY_NON_MODERATORS,
+        LOBBY_OPEN_TO_EVERYONE,
+        GUESTS_ALLOWED,
+        GUESTS_DISALLOWED,
+        PASSWORD_SET,
+        PASSWORD_REMOVED,
+        USER_ADDED,
+        USER_REMOVED,
+        GROUP_ADDED,
+        GROUP_REMOVED,
+        CIRCLE_ADDED,
+        CIRCLE_REMOVED,
+        MODERATOR_PROMOTED,
+        MODERATOR_DEMOTED,
+        GUEST_MODERATOR_PROMOTED,
+        GUEST_MODERATOR_DEMOTED,
+        MESSAGE_DELETED,
+        FILE_SHARED, OBJECT_SHARED,
+        MATTERBRIDGE_CONFIG_ADDED,
+        MATTERBRIDGE_CONFIG_EDITED,
+        MATTERBRIDGE_CONFIG_REMOVED,
+        MATTERBRIDGE_CONFIG_ENABLED,
+        MATTERBRIDGE_CONFIG_DISABLED,
+        CLEARED_CHAT,
+        REACTION,
+        REACTION_DELETED,
+        REACTION_REVOKED
+    }
+
+    companion object {
+        private const val TAG = "ChatMessage"
+    }
+}

+ 0 - 76
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java

@@ -1,76 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
- *
- * 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.chat;
-
-import com.bluelinelabs.logansquare.annotation.JsonField;
-import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.models.json.generic.GenericOCS;
-
-import org.parceler.Parcel;
-
-import java.util.List;
-
-@Parcel
-@JsonObject
-public class ChatOCS extends GenericOCS {
-    @JsonField(name = "data")
-    public List<ChatMessage> data;
-
-    public List<ChatMessage> getData() {
-        return this.data;
-    }
-
-    public void setData(List<ChatMessage> data) {
-        this.data = data;
-    }
-
-    public boolean equals(final Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof ChatOCS)) {
-            return false;
-        }
-        final ChatOCS other = (ChatOCS) o;
-        if (!other.canEqual((Object) this)) {
-            return false;
-        }
-        final Object this$data = this.getData();
-        final Object other$data = other.getData();
-
-        return this$data == null ? other$data == null : this$data.equals(other$data);
-    }
-
-    protected boolean canEqual(final Object other) {
-        return other instanceof ChatOCS;
-    }
-
-    public int hashCode() {
-        final int PRIME = 59;
-        int result = 1;
-        final Object $data = this.getData();
-        result = result * PRIME + ($data == null ? 43 : $data.hashCode());
-        return result;
-    }
-
-    public String toString() {
-        return "ChatOCS(data=" + this.getData() + ")";
-    }
-}

+ 38 - 0
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.kt

@@ -0,0 +1,38 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ *
+ * 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.chat
+
+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 kotlinx.android.parcel.Parcelize
+
+@Parcelize
+@JsonObject
+data class ChatOCS(
+    @JsonField(name = ["meta"])
+    var meta: GenericMeta?,
+    @JsonField(name = ["data"])
+    var data: List<ChatMessage>? = null
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, null)
+}

+ 0 - 74
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCSSingleMessage.java

@@ -1,74 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Marcel Hibbe
- * Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
- *
- * 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.chat;
-
-import com.bluelinelabs.logansquare.annotation.JsonField;
-import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.models.json.generic.GenericOCS;
-
-import org.parceler.Parcel;
-
-@Parcel
-@JsonObject
-public class ChatOCSSingleMessage extends GenericOCS {
-    @JsonField(name = "data")
-    public ChatMessage data;
-
-    public ChatMessage getData() {
-        return this.data;
-    }
-
-    public void setData(ChatMessage data) {
-        this.data = data;
-    }
-
-    public boolean equals(final Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof ChatOCSSingleMessage)) {
-            return false;
-        }
-        final ChatOCSSingleMessage other = (ChatOCSSingleMessage) o;
-        if (!other.canEqual((Object) this)) {
-            return false;
-        }
-        final Object this$data = this.getData();
-        final Object other$data = other.getData();
-
-        return this$data == null ? other$data == null : this$data.equals(other$data);
-    }
-
-    protected boolean canEqual(final Object other) {
-        return other instanceof ChatOCSSingleMessage;
-    }
-
-    public int hashCode() {
-        final int PRIME = 59;
-        int result = 1;
-        final Object $data = this.getData();
-        result = result * PRIME + ($data == null ? 43 : $data.hashCode());
-        return result;
-    }
-
-    public String toString() {
-        return "ChatOCSSingleMessage(data=" + this.getData() + ")";
-    }
-}

+ 38 - 0
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCSSingleMessage.kt

@@ -0,0 +1,38 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * 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.chat
+
+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 kotlinx.android.parcel.Parcelize
+
+@Parcelize
+@JsonObject
+data class ChatOCSSingleMessage(
+    @JsonField(name = ["meta"])
+    var meta: GenericMeta?,
+    @JsonField(name = ["data"])
+    var data: ChatMessage? = null
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, null)
+}

+ 0 - 624
app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java

@@ -1,624 +0,0 @@
-/*
- *
- *   Nextcloud Talk application
- *
- *   @author Mario Danic
- *   @author Tim Krüger
- *   Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
- *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
- *
- *   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.conversations;
-
-import com.bluelinelabs.logansquare.annotation.JsonField;
-import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.models.database.CapabilitiesUtil;
-import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.chat.ChatMessage;
-import com.nextcloud.talk.models.json.converters.EnumLobbyStateConverter;
-import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
-import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
-import com.nextcloud.talk.models.json.converters.EnumReadOnlyConversationConverter;
-import com.nextcloud.talk.models.json.converters.EnumRoomTypeConverter;
-import com.nextcloud.talk.models.json.participants.Participant;
-
-import org.parceler.Parcel;
-
-import java.util.HashMap;
-import java.util.Objects;
-
-@Parcel
-@JsonObject
-public class Conversation {
-    @JsonField(name = "id")
-    public String roomId;
-    @JsonField(name = "token")
-    public String token;
-    @JsonField(name = "name")
-    public String name;
-    @JsonField(name = "displayName")
-    public String displayName;
-    @JsonField(name = "description")
-    public String description;
-    @JsonField(name = "type", typeConverter = EnumRoomTypeConverter.class)
-    public ConversationType type;
-    @JsonField(name = "lastPing")
-    public long lastPing;
-    @Deprecated
-    @JsonField(name = "participants")
-    public HashMap<String, HashMap<String, Object>> participants;
-    @JsonField(name = "participantType", typeConverter = EnumParticipantTypeConverter.class)
-    public Participant.ParticipantType participantType;
-    @JsonField(name = "hasPassword")
-    public boolean hasPassword;
-    @JsonField(name = "sessionId")
-    public String sessionId;
-    @JsonField(name = "actorId")
-    public String actorId;
-    @JsonField(name = "actorType")
-    public String actorType;
-    public String password;
-    @JsonField(name = "isFavorite")
-    public boolean isFavorite;
-    @JsonField(name = "lastActivity")
-    public long lastActivity;
-    @JsonField(name = "unreadMessages")
-    public int unreadMessages;
-    @JsonField(name = "unreadMention")
-    public boolean unreadMention;
-    @JsonField(name = "lastMessage")
-    public ChatMessage lastMessage;
-    @JsonField(name = "objectType")
-    public String objectType;
-    @JsonField(name = "notificationLevel", typeConverter = EnumNotificationLevelConverter.class)
-    public NotificationLevel notificationLevel;
-    @JsonField(name = "readOnly", typeConverter = EnumReadOnlyConversationConverter.class)
-    public ConversationReadOnlyState conversationReadOnlyState;
-    @JsonField(name = "lobbyState", typeConverter = EnumLobbyStateConverter.class)
-    public LobbyState lobbyState;
-    @JsonField(name = "lobbyTimer")
-    public Long lobbyTimer;
-    @JsonField(name = "lastReadMessage")
-    public int lastReadMessage;
-    @JsonField(name = "hasCall")
-    public boolean hasCall;
-    @JsonField(name = "callFlag")
-    public int callFlag;
-    @JsonField(name = "canStartCall")
-    public boolean canStartCall;
-
-    @JsonField(name = "canLeaveConversation")
-    public Boolean canLeaveConversation;
-
-    @JsonField(name = "canDeleteConversation")
-    public Boolean canDeleteConversation;
-
-    @JsonField(name = "unreadMentionDirect")
-    public Boolean unreadMentionDirect;
-
-    @JsonField(name = "notificationCalls")
-    public Integer notificationCalls;
-
-    @JsonField(name = "permissions")
-    public int permissions;
-
-    public boolean isPublic() {
-        return (ConversationType.ROOM_PUBLIC_CALL.equals(type));
-    }
-
-    public boolean isGuest() {
-        return (Participant.ParticipantType.GUEST.equals(participantType) ||
-                Participant.ParticipantType.GUEST_MODERATOR.equals(participantType) ||
-                Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participantType));
-    }
-
-    private boolean isLockedOneToOne(UserEntity conversationUser) {
-        return (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL &&
-                CapabilitiesUtil.hasSpreedFeatureCapability(conversationUser, "locked-one-to-one-rooms"));
-    }
-
-    public boolean canModerate(UserEntity conversationUser) {
-        return (isParticipantOwnerOrModerator() && !isLockedOneToOne(conversationUser));
-    }
-
-    public boolean isParticipantOwnerOrModerator() {
-        return (Participant.ParticipantType.OWNER.equals(participantType) ||
-                Participant.ParticipantType.GUEST_MODERATOR.equals(participantType) ||
-                Participant.ParticipantType.MODERATOR.equals(participantType));
-    }
-
-    public boolean shouldShowLobby(UserEntity conversationUser) {
-        return LobbyState.LOBBY_STATE_MODERATORS_ONLY.equals(getLobbyState()) && !canModerate(conversationUser);
-    }
-
-    public boolean isLobbyViewApplicable(UserEntity conversationUser) {
-        return !canModerate(conversationUser) && (getType() == ConversationType.ROOM_GROUP_CALL || getType() == ConversationType.ROOM_PUBLIC_CALL);
-    }
-
-    public boolean isNameEditable(UserEntity conversationUser) {
-        return (canModerate(conversationUser) && !ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL.equals(type));
-    }
-
-    public boolean canLeave(UserEntity conversationUser) {
-        if (canLeaveConversation != null) {
-            // Available since APIv2
-            return canLeaveConversation;
-        }
-        // Fallback for APIv1
-        return !canModerate(conversationUser) ||
-            (getType() != ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL && this.participants.size() > 1);
-    }
-
-    public boolean canDelete(UserEntity conversationUser) {
-        if (canDeleteConversation != null) {
-            // Available since APIv2
-            return canDeleteConversation;
-        }
-        // Fallback for APIv1
-        return canModerate(conversationUser);
-    }
-
-    public String getRoomId() {
-        return this.roomId;
-    }
-
-    public String getToken() {
-        return this.token;
-    }
-
-    public String getName() {
-        return this.name;
-    }
-
-    public String getDescription() {
-        return this.description;
-    }
-
-    public String getDisplayName() {
-        return this.displayName;
-    }
-
-    public ConversationType getType() {
-        return this.type;
-    }
-
-    public long getLastPing() {
-        return this.lastPing;
-    }
-
-    public Participant.ParticipantType getParticipantType() {
-        return this.participantType;
-    }
-
-    public String getActorId() {
-        return actorId;
-    }
-
-    public String getActorType() {
-        return actorType;
-    }
-
-    public boolean isHasPassword() {
-        return this.hasPassword;
-    }
-
-    public String getSessionId() {
-        return this.sessionId;
-    }
-
-    public String getPassword() {
-        return this.password;
-    }
-
-    public boolean isFavorite() {
-        return this.isFavorite;
-    }
-
-    public long getLastActivity() {
-        return this.lastActivity;
-    }
-
-    public int getUnreadMessages() {
-        return this.unreadMessages;
-    }
-
-    public boolean isUnreadMention() {
-        return this.unreadMention;
-    }
-
-    public ChatMessage getLastMessage() {
-        return this.lastMessage;
-    }
-
-    public String getObjectType() {
-        return this.objectType;
-    }
-
-    public NotificationLevel getNotificationLevel() {
-        return this.notificationLevel;
-    }
-
-    public ConversationReadOnlyState getConversationReadOnlyState() {
-        return this.conversationReadOnlyState;
-    }
-
-    public LobbyState getLobbyState() {
-        return this.lobbyState;
-    }
-
-    public Long getLobbyTimer() {
-        return this.lobbyTimer;
-    }
-
-    public int getLastReadMessage() {
-        return this.lastReadMessage;
-    }
-
-    public boolean getHasCall() {
-        return hasCall;
-    }
-
-    public int getCallFlag() {
-        return this.callFlag;
-    }
-
-    public boolean getCanStartCall() {
-        return canStartCall;
-    }
-
-    public Boolean getUnreadMentionDirect() {
-        return unreadMentionDirect;
-    }
-
-    public Integer getNotificationCalls() { return notificationCalls; }
-
-    public int getPermissions() {
-        return permissions;
-    }
-
-    public void setRoomId(String roomId) {
-        this.roomId = roomId;
-    }
-
-    public void setToken(String token) {
-        this.token = token;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public void setDisplayName(String displayName) {
-        this.displayName = displayName;
-    }
-
-    public void setType(ConversationType type) {
-        this.type = type;
-    }
-
-    public void setLastPing(long lastPing) {
-        this.lastPing = lastPing;
-    }
-
-    @Deprecated
-    public void setParticipants(HashMap<String, HashMap<String, Object>> participants) {
-        this.participants = participants;
-    }
-
-    public void setParticipantType(Participant.ParticipantType participantType) {
-        this.participantType = participantType;
-    }
-
-    public void setActorId(String actorId) {
-        this.actorId = actorId;
-    }
-
-    public void setActorType(String actorType) {
-        this.actorType = actorType;
-    }
-
-    public void setHasPassword(boolean hasPassword) {
-        this.hasPassword = hasPassword;
-    }
-
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public void setFavorite(boolean isFavorite) {
-        this.isFavorite = isFavorite;
-    }
-
-    public void setLastActivity(long lastActivity) {
-        this.lastActivity = lastActivity;
-    }
-
-    public void setUnreadMessages(int unreadMessages) {
-        this.unreadMessages = unreadMessages;
-    }
-
-    public void setUnreadMention(boolean unreadMention) {
-        this.unreadMention = unreadMention;
-    }
-
-    public void setLastMessage(ChatMessage lastMessage) {
-        this.lastMessage = lastMessage;
-    }
-
-    public void setObjectType(String objectType) {
-        this.objectType = objectType;
-    }
-
-    public void setNotificationLevel(NotificationLevel notificationLevel) {
-        this.notificationLevel = notificationLevel;
-    }
-
-    public void setConversationReadOnlyState(ConversationReadOnlyState conversationReadOnlyState) {
-        this.conversationReadOnlyState = conversationReadOnlyState;
-    }
-
-    public void setLobbyState(LobbyState lobbyState) {
-        this.lobbyState = lobbyState;
-    }
-
-    public void setLobbyTimer(Long lobbyTimer) {
-        this.lobbyTimer = lobbyTimer;
-    }
-
-    public void setLastReadMessage(int lastReadMessage) {
-        this.lastReadMessage = lastReadMessage;
-    }
-
-    public void setHasCall(boolean hasCall) {
-        this.hasCall = hasCall;
-    }
-
-    public void setCallFlag(int callFlag) {
-        this.callFlag = callFlag;
-    }
-
-    public void setCanStartCall(boolean canStartCall) {
-        this.canStartCall = canStartCall;
-    }
-
-    public void setUnreadMentionDirect(Boolean unreadMentionDirect) {
-        this.unreadMentionDirect = unreadMentionDirect;
-    }
-
-    public void setPermissions(int permissions) {
-        this.permissions = permissions;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        Conversation that = (Conversation) o;
-
-        if (lastPing != that.lastPing) {
-            return false;
-        }
-        if (hasPassword != that.hasPassword) {
-            return false;
-        }
-        if (isFavorite != that.isFavorite) {
-            return false;
-        }
-        if (lastActivity != that.lastActivity) {
-            return false;
-        }
-        if (unreadMessages != that.unreadMessages) {
-            return false;
-        }
-        if (unreadMention != that.unreadMention) {
-            return false;
-        }
-        if (lastReadMessage != that.lastReadMessage) {
-            return false;
-        }
-        if (hasCall != that.hasCall) {
-            return false;
-        }
-        if (callFlag != that.callFlag) {
-            return false;
-        }
-        if (canStartCall != that.canStartCall) {
-            return false;
-        }
-        if (!Objects.equals(roomId, that.roomId)) {
-            return false;
-        }
-        if (!token.equals(that.token)) {
-            return false;
-        }
-        if (!Objects.equals(name, that.name)) {
-            return false;
-        }
-        if (!Objects.equals(displayName, that.displayName)) {
-            return false;
-        }
-        if (!Objects.equals(description, that.description)) {
-            return false;
-        }
-        if (type != that.type) {
-            return false;
-        }
-        if (!Objects.equals(participants, that.participants)) {
-            return false;
-        }
-        if (participantType != that.participantType) {
-            return false;
-        }
-        if (!Objects.equals(sessionId, that.sessionId)) {
-            return false;
-        }
-        if (!Objects.equals(actorId, that.actorId)) {
-            return false;
-        }
-        if (!Objects.equals(actorType, that.actorType)) {
-            return false;
-        }
-        if (!Objects.equals(password, that.password)) {
-            return false;
-        }
-        if (!Objects.equals(lastMessage, that.lastMessage)) {
-            return false;
-        }
-        if (!Objects.equals(objectType, that.objectType)) {
-            return false;
-        }
-        if (notificationLevel != that.notificationLevel) {
-            return false;
-        }
-        if (conversationReadOnlyState != that.conversationReadOnlyState) {
-            return false;
-        }
-        if (lobbyState != that.lobbyState) {
-            return false;
-        }
-        if (!Objects.equals(lobbyTimer, that.lobbyTimer)) {
-            return false;
-        }
-        if (!Objects.equals(canLeaveConversation, that.canLeaveConversation)) {
-            return false;
-        }
-        if (!Objects.equals(notificationCalls, that.notificationCalls)) {
-            return false;
-        }
-        if (permissions != that.permissions) {
-            return false;
-        }
-        return Objects.equals(canDeleteConversation, that.canDeleteConversation);
-    }
-
-    protected boolean canEqual(final Object other) {
-        return other instanceof Conversation;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = roomId != null ? roomId.hashCode() : 0;
-        result = 31 * result + token.hashCode();
-        result = 31 * result + (name != null ? name.hashCode() : 0);
-        result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
-        result = 31 * result + (description != null ? description.hashCode() : 0);
-        result = 31 * result + type.hashCode();
-        result = 31 * result + (int) (lastPing ^ (lastPing >>> 32));
-        result = 31 * result + (participants != null ? participants.hashCode() : 0);
-        result = 31 * result + (participantType != null ? participantType.hashCode() : 0);
-        result = 31 * result + (actorId != null ? actorId.hashCode() : 0);
-        result = 31 * result + (actorType != null ? actorType.hashCode() : 0);
-        result = 31 * result + (hasPassword ? 1 : 0);
-        result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
-        result = 31 * result + (password != null ? password.hashCode() : 0);
-        result = 31 * result + (isFavorite ? 1 : 0);
-        result = 31 * result + (int) (lastActivity ^ (lastActivity >>> 32));
-        result = 31 * result + unreadMessages;
-        result = 31 * result + (unreadMention ? 1 : 0);
-        result = 31 * result + (lastMessage != null ? lastMessage.hashCode() : 0);
-        result = 31 * result + (objectType != null ? objectType.hashCode() : 0);
-        result = 31 * result + (notificationLevel != null ? notificationLevel.hashCode() : 0);
-        result = 31 * result + (conversationReadOnlyState != null ? conversationReadOnlyState.hashCode() : 0);
-        result = 31 * result + (lobbyState != null ? lobbyState.hashCode() : 0);
-        result = 31 * result + (lobbyTimer != null ? lobbyTimer.hashCode() : 0);
-        result = 31 * result + lastReadMessage;
-        result = 31 * result + (hasCall ? 1 : 0);
-        result = 31 * result + callFlag;
-        result = 31 * result + (canStartCall ? 1 : 0);
-        result = 31 * result + (canLeaveConversation != null ? canLeaveConversation.hashCode() : 0);
-        result = 31 * result + (canDeleteConversation != null ? canDeleteConversation.hashCode() : 0);
-        result = 31 * result + (notificationCalls != null ? notificationCalls.hashCode() : 0);
-        result = 31 * result + permissions;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "Conversation{" +
-                "roomId='" + roomId + '\'' +
-                ", token='" + token + '\'' +
-                ", name='" + name + '\'' +
-                ", displayName='" + displayName + '\'' +
-                ", description='" + description + '\'' +
-                ", type=" + type +
-                ", lastPing=" + lastPing +
-                ", participants=" + participants +
-                ", participantType=" + participantType +
-                ", actorId=" + actorId +
-                ", actorType=" + actorType +
-                ", hasPassword=" + hasPassword +
-                ", sessionId='" + sessionId + '\'' +
-                ", password='" + password + '\'' +
-                ", isFavorite=" + isFavorite +
-                ", lastActivity=" + lastActivity +
-                ", unreadMessages=" + unreadMessages +
-                ", unreadMention=" + unreadMention +
-                ", lastMessage=" + lastMessage +
-                ", objectType='" + objectType + '\'' +
-                ", notificationLevel=" + notificationLevel +
-                ", conversationReadOnlyState=" + conversationReadOnlyState +
-                ", lobbyState=" + lobbyState +
-                ", lobbyTimer=" + lobbyTimer +
-                ", lastReadMessage=" + lastReadMessage +
-                ", hasCall=" + hasCall +
-                ", callFlag=" + callFlag +
-                ", canStartCall=" + canStartCall +
-                ", canLeaveConversation=" + canLeaveConversation +
-                ", canDeleteConversation=" + canDeleteConversation +
-                ", notificationCalls=" + notificationCalls +
-                ", permissions=" + permissions +
-                '}';
-    }
-
-    public enum NotificationLevel {
-        DEFAULT,
-        ALWAYS,
-        MENTION,
-        NEVER
-    }
-
-    public enum LobbyState {
-        LOBBY_STATE_ALL_PARTICIPANTS,
-        LOBBY_STATE_MODERATORS_ONLY
-    }
-
-    public enum ConversationReadOnlyState {
-        CONVERSATION_READ_WRITE,
-        CONVERSATION_READ_ONLY
-    }
-
-    @Parcel
-    public enum ConversationType {
-        DUMMY,
-        ROOM_TYPE_ONE_TO_ONE_CALL,
-        ROOM_GROUP_CALL,
-        ROOM_PUBLIC_CALL,
-        ROOM_SYSTEM
-    }
-
-}

+ 191 - 0
app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt

@@ -0,0 +1,191 @@
+/*
+ *
+ *   Nextcloud Talk application
+ *
+ *   @author Mario Danic
+ *   @author Tim Krüger
+ *   Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
+ *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
+ *
+ *   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.conversations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import com.nextcloud.talk.models.database.CapabilitiesUtil
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.models.json.chat.ChatMessage
+import com.nextcloud.talk.models.json.converters.EnumLobbyStateConverter
+import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
+import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter
+import com.nextcloud.talk.models.json.converters.EnumReadOnlyConversationConverter
+import com.nextcloud.talk.models.json.converters.EnumRoomTypeConverter
+import com.nextcloud.talk.models.json.participants.Participant.ParticipantType
+import kotlinx.android.parcel.Parcelize
+
+@Parcelize
+@JsonObject
+data class Conversation(
+    @JsonField(name = ["id"])
+    var roomId: String? = null,
+    @JsonField(name = ["token"])
+    var token: String? = null,
+    @JsonField(name = ["name"])
+    var name: String? = null,
+    @JsonField(name = ["displayName"])
+    var displayName: String? = null,
+    @JsonField(name = ["description"])
+    var description: String? = null,
+    @JsonField(name = ["type"], typeConverter = EnumRoomTypeConverter::class)
+    var type: ConversationType? = null,
+    @JsonField(name = ["lastPing"])
+    var lastPing: Long = 0,
+    @JsonField(name = ["participantType"], typeConverter = EnumParticipantTypeConverter::class)
+    var participantType: ParticipantType? = null,
+    @JsonField(name = ["hasPassword"])
+    var hasPassword: Boolean = false,
+    @JsonField(name = ["sessionId"])
+    var sessionId: String? = null,
+    @JsonField(name = ["actorId"])
+    var actorId: String? = null,
+    @JsonField(name = ["actorType"])
+    var actorType: String? = null,
+
+    var password: String? = null,
+
+    @JsonField(name = ["isFavorite"])
+    var favorite: Boolean = false,
+
+    @JsonField(name = ["lastActivity"])
+    var lastActivity: Long = 0,
+
+    @JsonField(name = ["unreadMessages"])
+    var unreadMessages: Int = 0,
+
+    @JsonField(name = ["unreadMention"])
+    var unreadMention: Boolean = false,
+
+    @JsonField(name = ["lastMessage"])
+    var lastMessage: ChatMessage? = null,
+
+    @JsonField(name = ["objectType"])
+    var objectType: String? = null,
+
+    @JsonField(name = ["notificationLevel"], typeConverter = EnumNotificationLevelConverter::class)
+    var notificationLevel: NotificationLevel? = null,
+
+    @JsonField(name = ["readOnly"], typeConverter = EnumReadOnlyConversationConverter::class)
+    var conversationReadOnlyState: ConversationReadOnlyState? = null,
+
+    @JsonField(name = ["lobbyState"], typeConverter = EnumLobbyStateConverter::class)
+    var lobbyState: LobbyState? = null,
+
+    @JsonField(name = ["lobbyTimer"])
+    var lobbyTimer: Long? = null,
+
+    @JsonField(name = ["lastReadMessage"])
+    var lastReadMessage: Int = 0,
+
+    @JsonField(name = ["hasCall"])
+    var hasCall: Boolean = false,
+
+    @JsonField(name = ["callFlag"])
+    var callFlag: Int = 0,
+
+    @JsonField(name = ["canStartCall"])
+    var canStartCall: Boolean = false,
+
+    @JsonField(name = ["canLeaveConversation"])
+    var canLeaveConversation: Boolean? = null,
+
+    @JsonField(name = ["canDeleteConversation"])
+    var canDeleteConversation: Boolean? = null,
+
+    @JsonField(name = ["unreadMentionDirect"])
+    var unreadMentionDirect: Boolean? = null,
+
+    @JsonField(name = ["notificationCalls"])
+    var notificationCalls: Int? = null,
+
+    @JsonField(name = ["permissions"])
+    var permissions: Int = 0
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, null)
+
+    val isPublic: Boolean
+        get() = ConversationType.ROOM_PUBLIC_CALL == type
+
+    val isGuest: Boolean
+        get() = ParticipantType.GUEST == participantType || ParticipantType.GUEST_MODERATOR == participantType || ParticipantType.USER_FOLLOWING_LINK == participantType
+
+    val isParticipantOwnerOrModerator: Boolean
+        get() = ParticipantType.OWNER == participantType || ParticipantType.GUEST_MODERATOR == participantType || ParticipantType.MODERATOR == participantType
+
+    private fun isLockedOneToOne(conversationUser: UserEntity): Boolean {
+        return type == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL &&
+            CapabilitiesUtil.hasSpreedFeatureCapability(conversationUser, "locked-one-to-one-rooms")
+    }
+
+    fun canModerate(conversationUser: UserEntity): Boolean {
+        return isParticipantOwnerOrModerator && !isLockedOneToOne(conversationUser)
+    }
+
+    fun shouldShowLobby(conversationUser: UserEntity): Boolean {
+        return LobbyState.LOBBY_STATE_MODERATORS_ONLY == lobbyState && !canModerate(conversationUser)
+    }
+
+    fun isLobbyViewApplicable(conversationUser: UserEntity): Boolean {
+        return !canModerate(conversationUser) && (type == ConversationType.ROOM_GROUP_CALL || type == ConversationType.ROOM_PUBLIC_CALL)
+    }
+
+    fun isNameEditable(conversationUser: UserEntity): Boolean {
+        return canModerate(conversationUser) && ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL != type
+    }
+
+    fun canLeave(): Boolean {
+        return if (canLeaveConversation != null) {
+            // Available since APIv2
+            canLeaveConversation!!
+        } else {
+            true
+        }
+    }
+
+    fun canDelete(conversationUser: UserEntity): Boolean {
+        return if (canDeleteConversation != null) {
+            // Available since APIv2
+            canDeleteConversation!!
+        } else canModerate(conversationUser)
+        // Fallback for APIv1
+    }
+
+    enum class NotificationLevel {
+        DEFAULT, ALWAYS, MENTION, NEVER
+    }
+
+    enum class LobbyState {
+        LOBBY_STATE_ALL_PARTICIPANTS, LOBBY_STATE_MODERATORS_ONLY
+    }
+
+    enum class ConversationReadOnlyState {
+        CONVERSATION_READ_WRITE, CONVERSATION_READ_ONLY
+    }
+
+    enum class ConversationType {
+        DUMMY, ROOM_TYPE_ONE_TO_ONE_CALL, ROOM_GROUP_CALL, ROOM_PUBLIC_CALL, ROOM_SYSTEM
+    }
+}

+ 15 - 14
app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOverall.kt

@@ -1,22 +1,23 @@
 /*
+ * Nextcloud Talk application
  *
- *   Nextcloud Talk application
+ * @author Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
  *
- *   @author Mario Danic
- *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
+ * 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 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.
  *
- *   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/>.
+ * 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.generic
 

+ 0 - 35
app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.java

@@ -1,35 +0,0 @@
-/*
- *
- *   Nextcloud Talk application
- *
- *   @author Mario Danic
- *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
- *
- *   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.participants;
-
-import com.bluelinelabs.logansquare.annotation.JsonField;
-import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.models.json.generic.GenericOCS;
-import com.nextcloud.talk.models.json.conversations.Conversation;
-
-@JsonObject
-public class AddParticipantOCS extends GenericOCS {
-    /*
-        Returned room will have only type set, and sometimes even that will be null
-     */
-    @JsonField(name = "data")
-    Conversation data;
-}

+ 42 - 0
app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.kt

@@ -0,0 +1,42 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ *
+ * 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.participants
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.models.json.generic.GenericMeta
+import kotlinx.android.parcel.Parcelize
+
+@Parcelize
+@JsonObject
+data class AddParticipantOCS(
+    @JsonField(name = ["meta"])
+    var meta: GenericMeta?,
+    /* Returned room will have only type set, and sometimes even that will be null */
+    @JsonField(name = ["data"])
+    var data: Conversation? = null
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, null)
+}

+ 0 - 3
app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOverall.kt

@@ -18,9 +18,6 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
- * https://github.com/nextcloud/ownCloud-Account-Importer
  */
 package com.nextcloud.talk.models.json.participants
 

+ 4 - 4
app/src/main/java/com/nextcloud/talk/ui/bottom/sheet/ProfileBottomSheet.kt

@@ -149,15 +149,15 @@ class ProfileBottomSheet(val ncApi: NcApi, val userEntity: UserEntity, val route
                 override fun onNext(roomOverall: RoomOverall) {
                     val bundle = Bundle()
                     bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, userEntity)
-                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken())
-                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId())
+                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().token)
+                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().roomId)
 
                     // FIXME once APIv2+ is used only, the createRoom already returns all the data
                     ncApi.getRoom(
                         credentials,
                         ApiUtils.getUrlForRoom(
                             apiVersion, userEntity.baseUrl,
-                            roomOverall.getOcs().getData().getToken()
+                            roomOverall.getOcs().getData().token
                         )
                     )
                         .subscribeOn(Schedulers.io())
@@ -174,7 +174,7 @@ class ProfileBottomSheet(val ncApi: NcApi, val userEntity: UserEntity, val route
                                 )
                                 ConductorRemapping.remapChatController(
                                     router, userEntity.id,
-                                    roomOverall.getOcs().getData().getToken(), bundle, true
+                                    roomOverall.getOcs().getData().token!!, bundle, true
                                 )
                             }
 

+ 12 - 12
app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt

@@ -102,10 +102,10 @@ class ConversationsListBottomDialog(
     }
 
     private fun initHeaderDescription() {
-        if (!TextUtils.isEmpty(conversation.getDisplayName())) {
-            binding.conversationOperationHeader.text = conversation.getDisplayName()
-        } else if (!TextUtils.isEmpty(conversation.getName())) {
-            binding.conversationOperationHeader.text = conversation.getName()
+        if (!TextUtils.isEmpty(conversation.displayName)) {
+            binding.conversationOperationHeader.text = conversation.displayName
+        } else if (!TextUtils.isEmpty(conversation.name)) {
+            binding.conversationOperationHeader.text = conversation.name
         }
     }
 
@@ -114,10 +114,10 @@ class ConversationsListBottomDialog(
         val canModerate = conversation.canModerate(currentUser)
 
         binding.conversationOperationRemoveFavorite.visibility = setVisibleIf(
-            hasFavoritesCapability && conversation.isFavorite()
+            hasFavoritesCapability && conversation.favorite
         )
         binding.conversationOperationAddFavorite.visibility = setVisibleIf(
-            hasFavoritesCapability && !conversation.isFavorite()
+            hasFavoritesCapability && !conversation.favorite
         )
 
         binding.conversationOperationMarkAsRead.visibility = setVisibleIf(
@@ -133,15 +133,15 @@ class ConversationsListBottomDialog(
         )
 
         binding.conversationOperationChangePassword.visibility = setVisibleIf(
-            canModerate && conversation.isHasPassword && conversation.isPublic
+            canModerate && conversation.hasPassword && conversation.isPublic
         )
 
         binding.conversationOperationClearPassword.visibility = setVisibleIf(
-            canModerate && conversation.isHasPassword && conversation.isPublic
+            canModerate && conversation.hasPassword && conversation.isPublic
         )
 
         binding.conversationOperationSetPassword.visibility = setVisibleIf(
-            canModerate && !conversation.isHasPassword && conversation.isPublic
+            canModerate && !conversation.hasPassword && conversation.isPublic
         )
 
         binding.conversationOperationDelete.visibility = setVisibleIf(
@@ -157,7 +157,7 @@ class ConversationsListBottomDialog(
         )
 
         binding.conversationOperationLeave.visibility = setVisibleIf(
-            conversation.canLeave(currentUser) &&
+            conversation.canLeave() &&
                 // leaving is by api not possible for the last user with moderator permissions.
                 // for now, hide this option for all moderators.
                 !conversation.canModerate(currentUser)
@@ -183,7 +183,7 @@ class ConversationsListBottomDialog(
 
         binding.conversationOperationLeave.setOnClickListener {
             val dataBuilder = Data.Builder()
-            dataBuilder.putString(KEY_ROOM_TOKEN, conversation.getToken())
+            dataBuilder.putString(KEY_ROOM_TOKEN, conversation.token)
             dataBuilder.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
             val data = dataBuilder.build()
 
@@ -197,7 +197,7 @@ class ConversationsListBottomDialog(
         }
 
         binding.conversationOperationDelete.setOnClickListener {
-            if (!TextUtils.isEmpty(conversation.getToken())) {
+            if (!TextUtils.isEmpty(conversation.token)) {
                 val bundle = Bundle()
                 bundle.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
                 bundle.putParcelable(KEY_ROOM, Parcels.wrap(conversation))

+ 2 - 2
app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt

@@ -83,12 +83,12 @@ class MessageActionsDialog(
         )
         initMenuDeleteMessage(showMessageDeletionButton)
         initMenuForwardMessage(
-            ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getMessageType() &&
+            ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() &&
                 !(message.isDeletedCommentMessage || message.isDeleted)
         )
         initMenuMarkAsUnread(
             message.previousMessageId > NO_PREVIOUS_MESSAGE_ID &&
-                ChatMessage.MessageType.SYSTEM_MESSAGE != message.getMessageType() &&
+                ChatMessage.MessageType.SYSTEM_MESSAGE != message.getCalculateMessageType() &&
                 BuildConfig.DEBUG
         )
     }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt

@@ -95,9 +95,9 @@ class ShowReactionsDialog(
 
     private fun initEmojiReactions() {
         adapter?.list?.clear()
-        if (chatMessage.reactions != null && chatMessage.reactions.isNotEmpty()) {
+        if (chatMessage.reactions != null && chatMessage.reactions!!.isNotEmpty()) {
             var reactionsTotal = 0
-            for ((emoji, amount) in chatMessage.reactions) {
+            for ((emoji, amount) in chatMessage.reactions!!) {
                 reactionsTotal = reactionsTotal.plus(amount as Int)
                 val tab: TabLayout.Tab = binding.emojiReactionsTabs.newTab() // Create a new Tab names "First Tab"
 

+ 6 - 6
app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt

@@ -58,14 +58,14 @@ class FileViewerUtils(private val context: Context, private val userEntity: User
         message: ChatMessage,
         progressUi: ProgressUi
     ) {
-        val fileName = message.getSelectedIndividualHashMap()[MagicPreviewMessageViewHolder.KEY_NAME]!!
-        val mimetype = message.getSelectedIndividualHashMap()[MagicPreviewMessageViewHolder.KEY_MIMETYPE]!!
-        val link = message.getSelectedIndividualHashMap()["link"]!!
+        val fileName = message.selectedIndividualHashMap!![MagicPreviewMessageViewHolder.KEY_NAME]!!
+        val mimetype = message.selectedIndividualHashMap!![MagicPreviewMessageViewHolder.KEY_MIMETYPE]!!
+        val link = message.selectedIndividualHashMap!!["link"]!!
 
-        val fileId = message.getSelectedIndividualHashMap()[MagicPreviewMessageViewHolder.KEY_ID]!!
-        val path = message.getSelectedIndividualHashMap()[MagicPreviewMessageViewHolder.KEY_PATH]!!
+        val fileId = message.selectedIndividualHashMap!![MagicPreviewMessageViewHolder.KEY_ID]!!
+        val path = message.selectedIndividualHashMap!![MagicPreviewMessageViewHolder.KEY_PATH]!!
 
-        var size = message.getSelectedIndividualHashMap()["size"]
+        var size = message.selectedIndividualHashMap!!["size"]
         if (size == null) {
             size = "-1"
         }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt

@@ -72,8 +72,8 @@ class SharedItemsViewModel(private val repository: SharedItemsRepository, privat
                 val mediaItems = response.body()!!.ocs!!.data
                 if (mediaItems != null) {
                     for (it in mediaItems) {
-                        if (it.value.messageParameters.containsKey("file")) {
-                            val fileParameters = it.value.messageParameters["file"]!!
+                        if (it.value.messageParameters!!.containsKey("file")) {
+                            val fileParameters = it.value.messageParameters!!["file"]!!
 
                             val previewAvailable =
                                 "yes".equals(fileParameters["preview-available"], ignoreCase = true)

+ 1 - 1
app/src/test/java/com/nextcloud/talk/utils/ShareUtilsTest.kt

@@ -69,7 +69,7 @@ class ShareUtilsTest {
         PowerMockito.mockStatic(TextUtils::class.java)
         Mockito.`when`(userUtils!!.currentUser).thenReturn(userEntity)
         Mockito.`when`(userEntity!!.baseUrl).thenReturn(baseUrl)
-        Mockito.`when`(conversation!!.getToken()).thenReturn(token)
+        Mockito.`when`(conversation!!.token).thenReturn(token)
         Mockito.`when`(context!!.resources).thenReturn(resources)
         Mockito.`when`(resources!!.getString(R.string.nc_share_text))
             .thenReturn("Join the conversation at %1\$s/index.php/call/%2\$s")