Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/talk-android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorAndy Scherzinger <info@andy-scherzinger.de>2021-05-09 20:20:21 +0300
committerGitHub <noreply@github.com>2021-05-09 20:20:21 +0300
commit16255b885f628753fe6ee4f35de80494c665fa3d (patch)
tree9344f7fb7489c5f406a3f0b98b888b2e56bd6ca6 /app/src
parent3ca2dfe860d41bfa0a75b1737f85c22314caafd8 (diff)
parent3cb2023680429d7cc92ecd41d52b1991b6d122ff (diff)
Merge pull request #1225 from nextcloud/feature/apiv4/fix-participant-list
[apiv4] šŸ‘„ Fix participant list
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java13
-rw-r--r--app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java65
-rw-r--r--app/src/main/java/com/nextcloud/talk/api/NcApi.java12
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/CallController.java6
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java2
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java7
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt403
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java15
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java58
-rw-r--r--app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java2
-rw-r--r--app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java203
-rw-r--r--app/src/main/java/com/nextcloud/talk/models/json/converters/EnumActorTypeConverter.kt58
-rw-r--r--app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java209
-rw-r--r--app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java4
-rw-r--r--app/src/main/res/values/strings.xml4
15 files changed, 714 insertions, 347 deletions
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
index 951592a10..75c55baab 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
@@ -21,6 +21,7 @@
package com.nextcloud.talk.adapters.items;
import android.accounts.Account;
+import android.net.Uri;
import android.view.View;
import android.widget.*;
import androidx.annotation.Nullable;
@@ -106,14 +107,14 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
holder.avatarImageView.setController(null);
if (adapter.hasFilter()) {
- FlexibleUtils.highlightText(holder.contactDisplayName, participant.getName(),
+ FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
} else {
- holder.contactDisplayName.setText(participant.getName());
+ holder.contactDisplayName.setText(participant.getDisplayName());
}
- holder.serverUrl.setText(userEntity.getBaseUrl());
+ holder.serverUrl.setText((Uri.parse(userEntity.getBaseUrl()).getHost()));
if (userEntity != null && userEntity.getBaseUrl() != null && userEntity.getBaseUrl().startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
holder.avatarImageView.setVisibility(View.VISIBLE);
@@ -122,7 +123,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
.setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
- participant.getUserId(), R.dimen.avatar_size), null))
+ participant.getActorId(), R.dimen.avatar_size), null))
.build();
holder.avatarImageView.setController(draweeController);
@@ -138,8 +139,8 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
@Override
public boolean filter(String constraint) {
- return participant.getName() != null &&
- Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getName().trim()).find();
+ return participant.getDisplayName() != null &&
+ Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getDisplayName().trim()).find();
}
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java
index 9968aab35..c1dfe7bf1 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java
@@ -21,7 +21,6 @@
package com.nextcloud.talk.adapters.items;
import android.content.res.Resources;
-import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
@@ -150,37 +149,38 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest));
}
- if (TextUtils.isEmpty(participant.getSource()) || participant.getSource().equals("users")) {
- if (Participant.ParticipantType.GUEST.equals(participant.getType()) ||
- Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participant.getType())) {
- String displayName = NextcloudTalkApplication.Companion.getSharedApplication()
- .getResources().getString(R.string.nc_guest);
-
- if (!TextUtils.isEmpty(participant.getDisplayName())) {
- displayName = participant.getDisplayName();
- }
-
- DraweeController draweeController = Fresco.newDraweeControllerBuilder()
- .setOldController(holder.simpleDraweeView.getController())
- .setAutoPlayAnimations(true)
- .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(),
- displayName, R.dimen.avatar_size), null))
- .build();
- holder.simpleDraweeView.setController(draweeController);
-
- } else {
+ if (participant.getActorType() == Participant.ActorType.GROUPS || "groups".equals(participant.getSource())) {
+ holder.simpleDraweeView.setImageResource(R.drawable.ic_circular_group);
+ } else if (participant.getActorType() == Participant.ActorType.EMAILS) {
+ // FIXME use an email icon
+ holder.simpleDraweeView.setImageResource(R.drawable.ic_circular_group);
+ } else if (participant.getActorType() == Participant.ActorType.GUESTS ||
+ Participant.ParticipantType.GUEST.equals(participant.getType()) ||
+ Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) {
- DraweeController draweeController = Fresco.newDraweeControllerBuilder()
- .setOldController(holder.simpleDraweeView.getController())
- .setAutoPlayAnimations(true)
- .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
- participant.getUserId(), R.dimen.avatar_size), null))
- .build();
- holder.simpleDraweeView.setController(draweeController);
+ String displayName = NextcloudTalkApplication.Companion.getSharedApplication()
+ .getResources().getString(R.string.nc_guest);
+ if (!TextUtils.isEmpty(participant.getDisplayName())) {
+ displayName = participant.getDisplayName();
}
- } else if ("groups".equals(participant.getSource())) {
- holder.simpleDraweeView.setImageResource(R.drawable.ic_circular_group);
+
+ DraweeController draweeController = Fresco.newDraweeControllerBuilder()
+ .setOldController(holder.simpleDraweeView.getController())
+ .setAutoPlayAnimations(true)
+ .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(),
+ displayName, R.dimen.avatar_size), null))
+ .build();
+ holder.simpleDraweeView.setController(draweeController);
+
+ } else if (participant.getActorType() == Participant.ActorType.USERS || participant.getSource().equals("users")) {
+ DraweeController draweeController = Fresco.newDraweeControllerBuilder()
+ .setOldController(holder.simpleDraweeView.getController())
+ .setAutoPlayAnimations(true)
+ .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
+ participant.getUserId(), R.dimen.avatar_size), null))
+ .build();
+ holder.simpleDraweeView.setController(draweeController);
}
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
@@ -246,13 +246,20 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
//userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner);
//break;
case 2:
+ case 6: // Guest moderator
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator);
break;
case 3:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user);
+ if (participant.getActorType() == Participant.ActorType.GROUPS) {
+ userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_group);
+ }
break;
case 4:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
+ if (participant.getActorType() == Participant.ActorType.EMAILS) {
+ userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_email);
+ }
break;
case 5:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link);
diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java
index 2daa2750c..2b16e13dd 100644
--- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java
+++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java
@@ -135,15 +135,27 @@ public interface NcApi {
// also used for removing a guest from a conversation
+ @Deprecated
@DELETE
Observable<GenericOverall> removeParticipantFromConversation(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
+ @DELETE
+ Observable<GenericOverall> removeAttendeeFromConversation(@Header("Authorization") String authorization, @Url String url, @Query("attendeeId") Long attendeeId);
+
+ @Deprecated
@POST
Observable<GenericOverall> promoteUserToModerator(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
+ @Deprecated
@DELETE
Observable<GenericOverall> demoteModeratorToUser(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
+ @POST
+ Observable<GenericOverall> promoteAttendeeToModerator(@Header("Authorization") String authorization, @Url String url, @Query("attendeeId") Long attendeeId);
+
+ @DELETE
+ Observable<GenericOverall> demoteAttendeeFromModerator(@Header("Authorization") String authorization, @Url String url, @Query("attendeeId") Long attendeeId);
+
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/participants/self
*/
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
index 89f3555f1..8859e8c40 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
@@ -1273,7 +1273,7 @@ public class CallController extends BaseController {
inCallFlag = (int) Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue();
}
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {1});
ncApi.joinCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken), inCallFlag)
.subscribeOn(Schedulers.io())
@@ -1558,7 +1558,7 @@ public class CallController extends BaseController {
}
private void hangupNetworkCalls(boolean shutDownView) {
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {1});
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io())
@@ -1686,7 +1686,7 @@ public class CallController extends BaseController {
private void getPeersForCall() {
Log.d(TAG, "getPeersForCall");
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {1});
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io())
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
index 8254dc60c..355bafbfb 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
@@ -209,7 +209,7 @@ public class CallNotificationController extends BaseController {
}
private void checkIfAnyParticipantsRemainInRoom() {
- int apiVersion = ApiUtils.getConversationApiVersion(userBeingCalled, new int[] {1});
+ int apiVersion = ApiUtils.getCallApiVersion(userBeingCalled, new int[] {1});
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, userBeingCalled.getBaseUrl(),
currentConversation.getToken()))
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
index 0e1b1fac0..fc9d2d8ce 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
@@ -61,6 +61,7 @@ import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall;
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomOverall;
+import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.ConductorRemapping;
@@ -508,6 +509,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
Participant participant;
List<AbstractFlexibleItem> newUserItemList = new ArrayList<>();
+ EnumActorTypeConverter actorTypeConverter = new EnumActorTypeConverter();
try {
AutocompleteOverall autocompleteOverall = LoganSquare.parse(responseBody.string(), AutocompleteOverall.class);
@@ -516,13 +518,14 @@ public class ContactsController extends BaseController implements SearchView.OnQ
for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) {
if (!autocompleteUser.getId().equals(currentUser.getUserId()) && !existingParticipants.contains(autocompleteUser.getId())) {
participant = new Participant();
- participant.setUserId(autocompleteUser.getId());
+ participant.setActorId(autocompleteUser.getId());
+ participant.setActorType(actorTypeConverter.getFromString(autocompleteUser.getSource()));
participant.setDisplayName(autocompleteUser.getLabel());
participant.setSource(autocompleteUser.getSource());
String headerTitle;
- if (!autocompleteUser.getSource().equals("groups")) {
+ if (participant.getActorType() != Participant.ActorType.GROUPS) {
headerTitle = participant.getDisplayName().substring(0, 1).toUpperCase();
} else {
headerTitle = getResources().getString(R.string.nc_groups);
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
index 3100500b2..6dee8e4ae 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
@@ -20,11 +20,13 @@
package com.nextcloud.talk.controllers
+import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.text.TextUtils
+import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
@@ -63,6 +65,8 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.participants.Participant
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.GROUPS
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.USERS
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
@@ -410,8 +414,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
for (i in participants.indices) {
participant = participants[i]
userItem = UserItem(participant, conversationUser, null)
- userItem.isOnline = !participant.sessionId.equals("0")
- if (!TextUtils.isEmpty(participant.userId) && participant.userId == conversationUser!!.userId) {
+ if (participant.sessionId != null) {
+ userItem.isOnline = !participant.sessionId.equals("0")
+ } else {
+ userItem.isOnline = !participant.sessionIds!!.isEmpty()
+ }
+
+ if (participant.getActorType() == USERS && participant.getActorId() == conversationUser!!.userId) {
ownUserItem = userItem
ownUserItem.model.sessionId = "-1"
ownUserItem.isOnline = true
@@ -444,7 +453,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
- apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
+ apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
}
ncApi.getPeersForCall(
@@ -478,7 +487,9 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
recyclerViewItems.forEach {
val userItem = it as UserItem
- existingParticipantsId.add(userItem.model.userId)
+ if (userItem.model.getActorType() == USERS) {
+ existingParticipantsId.add(userItem.model.getActorId())
+ }
}
bundle.putBoolean(BundleKeys.KEY_ADD_PARTICIPANTS, true)
@@ -572,7 +583,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
leaveConversationAction.visibility = View.VISIBLE
}
- if (!conversation!!.canModerate(conversationUser)) {
+ if (!conversation!!.canDelete(conversationUser)) {
deleteConversationAction.visibility = View.GONE
} else {
deleteConversationAction.visibility = View.VISIBLE
@@ -685,117 +696,320 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
}
+ private fun toggleModeratorStatus(apiVersion: Int, participant: Participant) {
+ val subscriber = object : Observer<GenericOverall> {
+ override fun onSubscribe(d: Disposable) {
+ }
+
+ override fun onNext(genericOverall: GenericOverall) {
+ getListOfParticipants()
+ }
+
+ @SuppressLint("LongLogTag")
+ override fun onError(e: Throwable) {
+ Log.e(TAG, "Error toggling moderator status", e)
+ }
+
+ override fun onComplete() {
+ }
+ }
+
+ if (participant.type == Participant.ParticipantType.MODERATOR ||
+ participant.type == Participant.ParticipantType.GUEST_MODERATOR
+ ) {
+ ncApi.demoteAttendeeFromModerator(
+ credentials,
+ ApiUtils.getUrlForRoomModerators(
+ apiVersion,
+ conversationUser!!.baseUrl,
+ conversation!!.token
+ ),
+ participant.attendeeId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(subscriber)
+ } else if (participant.type == Participant.ParticipantType.USER ||
+ participant.type == Participant.ParticipantType.GUEST
+ ) {
+ ncApi.promoteAttendeeToModerator(
+ credentials,
+ ApiUtils.getUrlForRoomModerators(
+ apiVersion,
+ conversationUser!!.baseUrl,
+ conversation!!.token
+ ),
+ participant.attendeeId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(subscriber)
+ }
+ }
+
+ private fun toggleModeratorStatusLegacy(apiVersion: Int, participant: Participant) {
+ val subscriber = object : Observer<GenericOverall> {
+ override fun onSubscribe(d: Disposable) {
+ }
+
+ override fun onNext(genericOverall: GenericOverall) {
+ getListOfParticipants()
+ }
+
+ @SuppressLint("LongLogTag")
+ override fun onError(e: Throwable) {
+ Log.e(TAG, "Error toggling moderator status", e)
+ }
+
+ override fun onComplete() {
+ }
+ }
+
+ if (participant.type == Participant.ParticipantType.MODERATOR) {
+ ncApi.demoteModeratorToUser(
+ credentials,
+ ApiUtils.getUrlForRoomModerators(
+ apiVersion,
+ conversationUser!!.baseUrl,
+ conversation!!.token
+ ),
+ participant.userId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(subscriber)
+ } else if (participant.type == Participant.ParticipantType.USER) {
+ ncApi.promoteUserToModerator(
+ credentials,
+ ApiUtils.getUrlForRoomModerators(
+ apiVersion,
+ conversationUser!!.baseUrl,
+ conversation!!.token
+ ),
+ participant.userId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(subscriber)
+ }
+ }
+
+ fun removeAttendeeFromConversation(apiVersion: Int, participant: Participant) {
+ if (apiVersion >= ApiUtils.APIv4) {
+ ncApi.removeAttendeeFromConversation(
+ credentials,
+ ApiUtils.getUrlForAttendees(
+ apiVersion,
+ conversationUser!!.baseUrl,
+ conversation!!.token
+ ),
+ participant.attendeeId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Observer<GenericOverall> {
+ override fun onSubscribe(d: Disposable) {
+ }
+
+ override fun onNext(genericOverall: GenericOverall) {
+ getListOfParticipants()
+ }
+
+ @SuppressLint("LongLogTag")
+ override fun onError(e: Throwable) {
+ Log.e(TAG, "Error removing attendee from conversation", e)
+ }
+
+ override fun onComplete() {
+ }
+ })
+ } else {
+ if (participant.type == Participant.ParticipantType.GUEST ||
+ participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK
+ ) {
+ ncApi.removeParticipantFromConversation(
+ credentials,
+ ApiUtils.getUrlForRemovingParticipantFromConversation(
+ conversationUser!!.baseUrl,
+ conversation!!.token,
+ true
+ ),
+ participant.sessionId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Observer<GenericOverall> {
+ override fun onSubscribe(d: Disposable) {
+ }
+
+ override fun onNext(genericOverall: GenericOverall) {
+ getListOfParticipants()
+ }
+
+ @SuppressLint("LongLogTag")
+ override fun onError(e: Throwable) {
+ Log.e(TAG, "Error removing guest from conversation", e)
+ }
+
+ override fun onComplete() {
+ }
+ })
+ } else {
+ ncApi.removeParticipantFromConversation(
+ credentials,
+ ApiUtils.getUrlForRemovingParticipantFromConversation(
+ conversationUser!!.baseUrl,
+ conversation!!.token,
+ false
+ ),
+ participant.userId
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Observer<GenericOverall> {
+ override fun onSubscribe(d: Disposable) {
+ }
+
+ override fun onNext(genericOverall: GenericOverall) {
+ getListOfParticipants()
+ }
+
+ @SuppressLint("LongLogTag")
+ override fun onError(e: Throwable) {
+ Log.e(TAG, "Error removing user from conversation", e)
+ }
+
+ override fun onComplete() {
+ }
+ })
+ }
+ }
+ }
+
override fun onItemClick(view: View?, position: Int): Boolean {
+ if (!conversation!!.canModerate(conversationUser)) {
+ return true
+ }
+
val userItem = adapter?.getItem(position) as UserItem
val participant = userItem.model
- if (participant.userId != conversationUser!!.userId) {
- var items = mutableListOf(
- BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_promote)),
- BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
+ val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
+
+ if (participant.getActorType() == USERS && participant.getActorId() == conversationUser!!.userId) {
+ if (participant.attendeePin.isNotEmpty()) {
+ val items = mutableListOf(
+ BasicListItemWithImage(
+ R.drawable.ic_lock_grey600_24px,
+ context.getString(R.string.nc_attendee_pin, participant.attendeePin)
+ )
+ )
+ MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+ cornerRadius(res = R.dimen.corner_radius)
+
+ title(text = participant.displayName)
+ listItemsWithImage(items = items) { dialog, index, _ ->
+ if (index == 0) {
+ removeAttendeeFromConversation(apiVersion, participant)
+ }
+ }
+ }
+ }
+ return true
+ }
+
+ if (participant.type == Participant.ParticipantType.OWNER) {
+ // Can not moderate owner
+ return true
+ }
+
+ if (participant.getActorType() == GROUPS) {
+ val items = mutableListOf(
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
- context.getString(R.string.nc_remove_participant)
+ context.getString(R.string.nc_remove_group_and_members)
)
)
+ MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+ cornerRadius(res = R.dimen.corner_radius)
- if (!conversation!!.canModerate(conversationUser)) {
- items = mutableListOf()
- } else {
- if (participant.type == Participant.ParticipantType.MODERATOR || participant.type == Participant.ParticipantType.OWNER) {
- items.removeAt(0)
- } else if (participant.type == Participant.ParticipantType.USER) {
- items.removeAt(1)
+ title(text = participant.displayName)
+ listItemsWithImage(items = items) { dialog, index, _ ->
+ if (index == 0) {
+ removeAttendeeFromConversation(apiVersion, participant)
+ }
}
}
+ return true
+ }
- if (items.isNotEmpty()) {
- MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
- cornerRadius(res = R.dimen.corner_radius)
+ var items = mutableListOf(
+ BasicListItemWithImage(
+ R.drawable.ic_lock_grey600_24px,
+ context.getString(R.string.nc_attendee_pin, participant.attendeePin)
+ ),
+ BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_promote)),
+ BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
+ BasicListItemWithImage(
+ R.drawable.ic_delete_grey600_24dp,
+ context.getString(R.string.nc_remove_participant)
+ )
+ )
- title(text = participant.displayName)
- listItemsWithImage(items = items) { dialog, index, _ ->
+ if (participant.type == Participant.ParticipantType.MODERATOR ||
+ participant.type == Participant.ParticipantType.GUEST_MODERATOR
+ ) {
+ items.removeAt(1)
+ } else if (participant.type == Participant.ParticipantType.USER ||
+ participant.type == Participant.ParticipantType.GUEST
+ ) {
+ items.removeAt(2)
+ } else {
+ // Self joined users can not be promoted nor demoted
+ items.removeAt(2)
+ items.removeAt(1)
+ }
- val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
+ if (participant.attendeePin.isEmpty()) {
+ items.removeAt(0)
+ }
- if (index == 0) {
- if (participant.type == Participant.ParticipantType.MODERATOR) {
- ncApi.demoteModeratorToUser(
- credentials,
- ApiUtils.getUrlForRoomModerators(
- apiVersion,
- conversationUser.baseUrl,
- conversation!!.token
- ),
- participant.userId
- )
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
- getListOfParticipants()
- }
- } else if (participant.type == Participant.ParticipantType.USER) {
- ncApi.promoteUserToModerator(
- credentials,
- ApiUtils.getUrlForRoomModerators(
- apiVersion,
- conversationUser.baseUrl,
- conversation!!.token
- ),
- participant.userId
- )
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
- getListOfParticipants()
- }
- }
- } else if (index == 1) {
- if (participant.type == Participant.ParticipantType.GUEST ||
- participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK
- ) {
- ncApi.removeParticipantFromConversation(
- credentials,
- ApiUtils.getUrlForRemovingParticipantFromConversation(
- conversationUser.baseUrl,
- conversation!!.token,
- true
- ),
- participant.sessionId
- )
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
- getListOfParticipants()
- }
- } else {
- ncApi.removeParticipantFromConversation(
- credentials,
- ApiUtils.getUrlForRemovingParticipantFromConversation(
- conversationUser.baseUrl,
- conversation!!.token,
- false
- ),
- participant.userId
- )
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
- getListOfParticipants()
- // get participants again
- }
- }
+ if (items.isNotEmpty()) {
+ MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+ cornerRadius(res = R.dimen.corner_radius)
+
+ title(text = participant.displayName)
+ listItemsWithImage(items = items) { dialog, index, _ ->
+ var actionToTrigger = index
+ if (participant.attendeePin.isEmpty()) {
+ actionToTrigger++
+ }
+ if (participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK) {
+ actionToTrigger++
+ }
+
+ if (actionToTrigger == 0) {
+ // Pin, nothing to do
+ } else if (actionToTrigger == 1) {
+ // Promote/demote
+ if (apiVersion >= ApiUtils.APIv4) {
+ toggleModeratorStatus(apiVersion, participant)
+ } else {
+ toggleModeratorStatusLegacy(apiVersion, participant)
}
+ } else if (actionToTrigger == 2) {
+ // Remove from conversation
+ removeAttendeeFromConversation(apiVersion, participant)
}
}
}
}
-
return true
}
companion object {
+ private const val TAG = "ConversationInfoController"
private const val ID_DELETE_CONVERSATION_DIALOG = 0
}
@@ -804,6 +1018,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
*/
class UserItemComparator : Comparator<UserItem> {
override fun compare(left: UserItem, right: UserItem): Int {
+ val leftIsGroup = left.model.actorType == GROUPS
+ val rightIsGroup = right.model.actorType == GROUPS
+ if (leftIsGroup != rightIsGroup) {
+ // Groups below participants
+ return if (rightIsGroup) { -1 } else { 1 }
+ }
+
if (left.isOnline && !right.isOnline) {
return -1
} else if (!left.isOnline && right.isOnline) {
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
index e725ed838..c07cb4f32 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
@@ -178,17 +178,17 @@ public class SwitchAccountController extends BaseController {
for (Object userEntityObject : userUtils.getUsers()) {
userEntity = (UserEntity) userEntityObject;
if (!userEntity.getCurrent()) {
- participant = new Participant();
- participant.setName(userEntity.getDisplayName());
-
String userId;
-
if (userEntity.getUserId() != null) {
userId = userEntity.getUserId();
} else {
userId = userEntity.getUsername();
}
- participant.setUserId(userId);
+
+ participant = new Participant();
+ participant.setActorType(Participant.ActorType.USERS);
+ participant.setActorId(userId);
+ participant.setDisplayName(userEntity.getDisplayName());
userItems.add(new AdvancedUserItem(participant, userEntity, null));
}
}
@@ -203,8 +203,9 @@ public class SwitchAccountController extends BaseController {
importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
participant = new Participant();
- participant.setName(importAccount.getUsername());
- participant.setUserId(importAccount.getUsername());
+ participant.setActorType(Participant.ActorType.USERS);
+ participant.setActorId(importAccount.getUsername());
+ participant.setDisplayName(importAccount.getUsername());
userEntity = new UserEntity();
userEntity.setBaseUrl(importAccount.getBaseUrl());
userItems.add(new AdvancedUserItem(participant, userEntity, account));
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
index 23705faa4..69811b8d9 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
@@ -54,7 +54,6 @@ import com.nextcloud.talk.models.json.capabilities.Capabilities;
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomOverall;
-import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.ConductorRemapping;
@@ -270,29 +269,20 @@ public class OperationsMenuController extends BaseController {
break;
case 11:
RetrofitBucket retrofitBucket;
- boolean isGroupCallWorkaround = false;
String invite = null;
if (invitedGroups.size() > 0) {
invite = invitedGroups.get(0);
}
- if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) ||
- !currentUser.hasSpreedFeatureCapability("empty-group-room")) {
+ if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL)) {
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
- "3", invite, conversationName);
+ "3", invite, conversationName);
} else {
- String roomType = "2";
- if (!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
- isGroupCallWorkaround = true;
- roomType = "3";
- }
-
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
- roomType, invite, conversationName);
+ "2", invite, conversationName);
}
- final boolean isGroupCallWorkaroundFinal = isGroupCallWorkaround;
ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -321,11 +311,7 @@ public class OperationsMenuController extends BaseController {
@Override
public void onNext(RoomOverall roomOverall) {
conversation = roomOverall.getOcs().getData();
- if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) && isGroupCallWorkaroundFinal) {
- performGroupCallWorkaround(credentials);
- } else {
- inviteUsersToAConversation();
- }
+ inviteUsersToAConversation();
}
@Override
@@ -393,40 +379,6 @@ public class OperationsMenuController extends BaseController {
}
}
- private void performGroupCallWorkaround(String credentials) {
- int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
-
- ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
- conversation.getToken()))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .retry(1)
- .subscribe(new Observer<GenericOverall>() {
- @Override
- public void onSubscribe(Disposable d) {
-
- }
-
- @Override
- public void onNext(GenericOverall genericOverall) {
- inviteUsersToAConversation();
- }
-
- @Override
- public void onError(Throwable e) {
- showResultImage(false, false);
- dispose();
- }
-
- @Override
- public void onComplete() {
- dispose();
- }
- });
-
-
- }
-
private void showResultImage(boolean everythingOK, boolean isGuestSupportError) {
progressBar.setVisibility(View.GONE);
@@ -552,7 +504,7 @@ public class OperationsMenuController extends BaseController {
localInvitedGroups.remove(0);
}
- int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {1});
+ int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {4, 1});
if (localInvitedUsers.size() > 0 || (localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) {
if ((localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) {
diff --git a/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java b/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
index cf0b6846e..947e9693a 100644
--- a/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
+++ b/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
@@ -66,7 +66,7 @@ public class AddParticipantsToConversation extends Worker {
String[] selectedGroupIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_GROUPS());
UserEntity user = userUtils.getUserWithInternalId(data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1));
- int apiVersion = ApiUtils.getConversationApiVersion(user, new int[] {1});
+ int apiVersion = ApiUtils.getConversationApiVersion(user, new int[] {ApiUtils.APIv4, 1});
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken());
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java b/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java
index 882a298c2..9a40f9aa3 100644
--- a/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java
+++ b/app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java
@@ -84,9 +84,13 @@ public class Conversation {
public int lastReadMessage;
@JsonField(name = "callFlag")
public int callFlag;
+
@JsonField(name = "canLeaveConversation")
public Boolean canLeaveConversation;
+ @JsonField(name = "canDeleteConversation")
+ public Boolean canDeleteConversation;
+
public boolean isPublic() {
return (ConversationType.ROOM_PUBLIC_CALL.equals(type));
}
@@ -133,6 +137,15 @@ public class Conversation {
(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;
}
@@ -314,169 +327,155 @@ public class Conversation {
this.callFlag = callFlag;
}
- public boolean equals(final Object o) {
- if (o == this) {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
return true;
}
- if (!(o instanceof Conversation)) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Conversation that = (Conversation) o;
+
+ if (lastPing != that.lastPing) {
return false;
}
- final Conversation other = (Conversation) o;
- if (!other.canEqual((Object) this)) {
+ if (hasPassword != that.hasPassword) {
return false;
}
- final Object this$roomId = this.getRoomId();
- final Object other$roomId = other.getRoomId();
- if (this$roomId == null ? other$roomId != null : !this$roomId.equals(other$roomId)) {
+ if (isFavorite != that.isFavorite) {
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)) {
+ if (lastActivity != that.lastActivity) {
return false;
}
- final Object this$name = this.getName();
- final Object other$name = other.getName();
- if (this$name == null ? other$name != null : !this$name.equals(other$name)) {
+ if (unreadMessages != that.unreadMessages) {
return false;
}
- final Object this$displayName = this.getDisplayName();
- final Object other$displayName = other.getDisplayName();
- if (this$displayName == null ? other$displayName != null : !this$displayName.equals(other$displayName)) {
+ if (unreadMention != that.unreadMention) {
return false;
}
- final Object this$type = this.getType();
- final Object other$type = other.getType();
- if (this$type == null ? other$type != null : !this$type.equals(other$type)) {
+ if (lastReadMessage != that.lastReadMessage) {
return false;
}
- if (this.getLastPing() != other.getLastPing()) {
+ if (callFlag != that.callFlag) {
return false;
}
- final Object this$participants = this.participants;
- final Object other$participants = other.participants;
- if (this$participants == null ? other$participants != null : !this$participants.equals(other$participants)) {
+ if (roomId != null ? !roomId.equals(that.roomId) : that.roomId != null) {
return false;
}
- final Object this$participantType = this.getParticipantType();
- final Object other$participantType = other.getParticipantType();
- if (this$participantType == null ? other$participantType != null : !this$participantType.equals(other$participantType)) {
+ if (!token.equals(that.token)) {
return false;
}
- if (this.isHasPassword() != other.isHasPassword()) {
+ if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
- final Object this$sessionId = this.getSessionId();
- final Object other$sessionId = other.getSessionId();
- if (this$sessionId == null ? other$sessionId != null : !this$sessionId.equals(other$sessionId)) {
+ if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) {
return false;
}
- final Object this$password = this.getPassword();
- final Object other$password = other.getPassword();
- if (this$password == null ? other$password != null : !this$password.equals(other$password)) {
+ if (type != that.type) {
return false;
}
- if (this.isFavorite() != other.isFavorite()) {
+ if (participants != null ? !participants.equals(that.participants) : that.participants != null) {
return false;
}
- if (this.getLastActivity() != other.getLastActivity()) {
+ if (participantType != that.participantType) {
return false;
}
- if (this.getUnreadMessages() != other.getUnreadMessages()) {
+ if (sessionId != null ? !sessionId.equals(that.sessionId) : that.sessionId != null) {
return false;
}
- if (this.isUnreadMention() != other.isUnreadMention()) {
+ if (password != null ? !password.equals(that.password) : that.password != null) {
return false;
}
- final Object this$lastMessage = this.getLastMessage();
- final Object other$lastMessage = other.getLastMessage();
- if (this$lastMessage == null ? other$lastMessage != null : !this$lastMessage.equals(other$lastMessage)) {
+ if (lastMessage != null ? !lastMessage.equals(that.lastMessage) : that.lastMessage != null) {
return false;
}
- final Object this$objectType = this.getObjectType();
- final Object other$objectType = other.getObjectType();
- if (this$objectType == null ? other$objectType != null : !this$objectType.equals(other$objectType)) {
+ if (objectType != null ? !objectType.equals(that.objectType) : that.objectType != null) {
return false;
}
- final Object this$notificationLevel = this.getNotificationLevel();
- final Object other$notificationLevel = other.getNotificationLevel();
- if (this$notificationLevel == null ? other$notificationLevel != null : !this$notificationLevel.equals(other$notificationLevel)) {
+ if (notificationLevel != that.notificationLevel) {
return false;
}
- final Object this$conversationReadOnlyState = this.getConversationReadOnlyState();
- final Object other$conversationReadOnlyState = other.getConversationReadOnlyState();
- if (this$conversationReadOnlyState == null ? other$conversationReadOnlyState != null : !this$conversationReadOnlyState.equals(other$conversationReadOnlyState)) {
+ if (conversationReadOnlyState != that.conversationReadOnlyState) {
return false;
}
- final Object this$lobbyState = this.getLobbyState();
- final Object other$lobbyState = other.getLobbyState();
- if (this$lobbyState == null ? other$lobbyState != null : !this$lobbyState.equals(other$lobbyState)) {
+ if (lobbyState != that.lobbyState) {
return false;
}
- final Object this$lobbyTimer = this.getLobbyTimer();
- final Object other$lobbyTimer = other.getLobbyTimer();
- if (this$lobbyTimer == null ? other$lobbyTimer != null : !this$lobbyTimer.equals(other$lobbyTimer)) {
+ if (lobbyTimer != null ? !lobbyTimer.equals(that.lobbyTimer) : that.lobbyTimer != null) {
return false;
}
- if (this.getLastReadMessage() != other.getLastReadMessage()) {
+ if (canLeaveConversation != null ? !canLeaveConversation.equals(that.canLeaveConversation) : that.canLeaveConversation != null) {
return false;
}
-
- return this.getCallFlag() == other.getCallFlag();
+ return canDeleteConversation != null ? canDeleteConversation.equals(that.canDeleteConversation) : that.canDeleteConversation == null;
}
protected boolean canEqual(final Object other) {
return other instanceof Conversation;
}
+ @Override
public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- final Object $roomId = this.getRoomId();
- result = result * PRIME + ($roomId == null ? 43 : $roomId.hashCode());
- final Object $token = this.getToken();
- result = result * PRIME + ($token == null ? 43 : $token.hashCode());
- final Object $name = this.getName();
- result = result * PRIME + ($name == null ? 43 : $name.hashCode());
- final Object $displayName = this.getDisplayName();
- result = result * PRIME + ($displayName == null ? 43 : $displayName.hashCode());
- final Object $type = this.getType();
- result = result * PRIME + ($type == null ? 43 : $type.hashCode());
- final long $lastPing = this.getLastPing();
- result = result * PRIME + (int) ($lastPing >>> 32 ^ $lastPing);
- final Object $participants = this.participants;
- result = result * PRIME + ($participants == null ? 43 : $participants.hashCode());
- final Object $participantType = this.getParticipantType();
- result = result * PRIME + ($participantType == null ? 43 : $participantType.hashCode());
- result = result * PRIME + (this.isHasPassword() ? 79 : 97);
- final Object $sessionId = this.getSessionId();
- result = result * PRIME + ($sessionId == null ? 43 : $sessionId.hashCode());
- final Object $password = this.getPassword();
- result = result * PRIME + ($password == null ? 43 : $password.hashCode());
- result = result * PRIME + (this.isFavorite() ? 79 : 97);
- final long $lastActivity = this.getLastActivity();
- result = result * PRIME + (int) ($lastActivity >>> 32 ^ $lastActivity);
- result = result * PRIME + this.getUnreadMessages();
- result = result * PRIME + (this.isUnreadMention() ? 79 : 97);
- final Object $lastMessage = this.getLastMessage();
- result = result * PRIME + ($lastMessage == null ? 43 : $lastMessage.hashCode());
- final Object $objectType = this.getObjectType();
- result = result * PRIME + ($objectType == null ? 43 : $objectType.hashCode());
- final Object $notificationLevel = this.getNotificationLevel();
- result = result * PRIME + ($notificationLevel == null ? 43 : $notificationLevel.hashCode());
- final Object $conversationReadOnlyState = this.getConversationReadOnlyState();
- result = result * PRIME + ($conversationReadOnlyState == null ? 43 : $conversationReadOnlyState.hashCode());
- final Object $lobbyState = this.getLobbyState();
- result = result * PRIME + ($lobbyState == null ? 43 : $lobbyState.hashCode());
- final Object $lobbyTimer = this.getLobbyTimer();
- result = result * PRIME + ($lobbyTimer == null ? 43 : $lobbyTimer.hashCode());
- result = result * PRIME + this.getLastReadMessage();
- result = result * PRIME + this.getCallFlag();
+ 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 + 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 + (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 + callFlag;
+ result = 31 * result + (canLeaveConversation != null ? canLeaveConversation.hashCode() : 0);
+ result = 31 * result + (canDeleteConversation != null ? canDeleteConversation.hashCode() : 0);
return result;
}
+ @Override
public String toString() {
- return "Conversation(roomId=" + this.getRoomId() + ", token=" + this.getToken() + ", name=" + this.getName() + ", displayName=" + this.getDisplayName() + ", type=" + this.getType() + ", lastPing=" + this.getLastPing() + ", participants=" + this.participants + ", participantType=" + this.getParticipantType() + ", hasPassword=" + this.isHasPassword() + ", sessionId=" + this.getSessionId() + ", password=" + this.getPassword() + ", isFavorite=" + this.isFavorite() + ", lastActivity=" + this.getLastActivity() + ", unreadMessages=" + this.getUnreadMessages() + ", unreadMention=" + this.isUnreadMention() + ", lastMessage=" + this.getLastMessage() + ", objectType=" + this.getObjectType() + ", notificationLevel=" + this.getNotificationLevel() + ", conversationReadOnlyState=" + this.getConversationReadOnlyState() + ", lobbyState=" + this.getLobbyState() + ", lobbyTimer=" + this.getLobbyTimer() + ", lastReadMessage=" + this.getLastReadMessage() + ", callFlag=" + this.getCallFlag() + ")";
+ return "Conversation{" +
+ "roomId='" + roomId + '\'' +
+ ", token='" + token + '\'' +
+ ", name='" + name + '\'' +
+ ", displayName='" + displayName + '\'' +
+ ", type=" + type +
+ ", lastPing=" + lastPing +
+ ", participants=" + participants +
+ ", participantType=" + participantType +
+ ", 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 +
+ ", callFlag=" + callFlag +
+ ", canLeaveConversation=" + canLeaveConversation +
+ ", canDeleteConversation=" + canDeleteConversation +
+ '}';
}
public enum NotificationLevel {
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/converters/EnumActorTypeConverter.kt b/app/src/main/java/com/nextcloud/talk/models/json/converters/EnumActorTypeConverter.kt
new file mode 100644
index 000000000..ca7407a36
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/models/json/converters/EnumActorTypeConverter.kt
@@ -0,0 +1,58 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Joas Schilling
+ * @author Andy Scherzinger
+ * Copyright (C) 2021 Joas Schilling <coding@schilljs.com>
+ * Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.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.converters
+
+import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
+import com.nextcloud.talk.models.json.participants.Participant
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.DUMMY
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.EMAILS
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.GROUPS
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.GUESTS
+import com.nextcloud.talk.models.json.participants.Participant.ActorType.USERS
+
+class EnumActorTypeConverter : StringBasedTypeConverter<Participant.ActorType>() {
+ override fun getFromString(string: String): Participant.ActorType {
+ return when (string) {
+ "emails" -> EMAILS
+ "groups" -> GROUPS
+ "guests" -> GUESTS
+ "users" -> USERS
+ else -> DUMMY
+ }
+ }
+
+ override fun convertToString(`object`: Participant.ActorType?): String {
+
+ if (`object` == null) {
+ return ""
+ }
+
+ return when (`object`) {
+ EMAILS -> "emails"
+ GROUPS -> "groups"
+ GUESTS -> "guests"
+ USERS -> "users"
+ else -> ""
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java b/app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java
index 5832a0461..71a9db829 100644
--- a/app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java
+++ b/app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java
@@ -22,21 +22,38 @@ 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.converters.EnumActorTypeConverter;
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
import com.nextcloud.talk.models.json.converters.ObjectParcelConverter;
import org.parceler.Parcel;
import org.parceler.ParcelPropertyConverter;
+import java.util.Arrays;
+
@Parcel
@JsonObject
public class Participant {
+ @JsonField(name = "attendeeId")
+ public Long attendeeId;
+
+ @JsonField(name = "actorType", typeConverter = EnumActorTypeConverter.class)
+ public ActorType actorType;
+
+ @JsonField(name = "actorId")
+ public String actorId;
+
+ @JsonField(name = "attendeePin")
+ public String attendeePin;
+
+ @Deprecated
@JsonField(name = "userId")
public String userId;
@JsonField(name = {"type", "participantType"}, typeConverter = EnumParticipantTypeConverter.class)
public ParticipantType type;
+ @Deprecated
@JsonField(name = "name")
public String name;
@@ -46,15 +63,21 @@ public class Participant {
@JsonField(name = "lastPing")
public long lastPing;
+ @Deprecated
@JsonField(name = "sessionId")
public String sessionId;
+ @JsonField(name = "sessionIds")
+ public String[] sessionIds;
+
+ @Deprecated
@JsonField(name = "roomId")
public long roomId;
@ParcelPropertyConverter(ObjectParcelConverter.class)
@JsonField(name = "inCall")
public Object inCall;
+
public String source;
public boolean selected;
@@ -76,7 +99,37 @@ public class Participant {
return participantFlags;
}
+ public Long getAttendeeId() {
+ return attendeeId;
+ }
+
+ public ActorType getActorType() {
+ if (this.actorType == null) {
+ if (this.userId != null) {
+ return ActorType.USERS;
+ } else {
+ return ActorType.GUESTS;
+ }
+ }
+ return actorType;
+ }
+
+ public String getActorId() {
+ if (this.actorId == null) {
+ return this.userId;
+ }
+ return actorId;
+ }
+
+ public String getAttendeePin() {
+ return attendeePin;
+ }
+
+ @Deprecated
public String getUserId() {
+ if (this.actorType != null && this.actorType == ActorType.USERS) {
+ return this.actorId;
+ }
return this.userId;
}
@@ -84,6 +137,7 @@ public class Participant {
return this.type;
}
+ @Deprecated
public String getName() {
return this.name;
}
@@ -96,10 +150,16 @@ public class Participant {
return this.lastPing;
}
+ @Deprecated
public String getSessionId() {
return this.sessionId;
}
+ public String[] getSessionIds() {
+ return sessionIds;
+ }
+
+ @Deprecated
public long getRoomId() {
return this.roomId;
}
@@ -116,14 +176,32 @@ public class Participant {
return this.selected;
}
+ @Deprecated
public void setUserId(String userId) {
this.userId = userId;
}
+ public void setAttendeeId(Long attendeeId) {
+ this.attendeeId = attendeeId;
+ }
+
+ public void setActorType(ActorType actorType) {
+ this.actorType = actorType;
+ }
+
+ public void setActorId(String actorId) {
+ this.actorId = actorId;
+ }
+
+ public void setAttendeePin(String attendeePin) {
+ this.attendeePin = attendeePin;
+ }
+
public void setType(ParticipantType type) {
this.type = type;
}
+ @Deprecated
public void setName(String name) {
this.name = name;
}
@@ -136,10 +214,12 @@ public class Participant {
this.lastPing = lastPing;
}
+ @Deprecated
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
+ @Deprecated
public void setRoomId(long roomId) {
this.roomId = roomId;
}
@@ -156,93 +236,118 @@ public class Participant {
this.selected = selected;
}
- public boolean equals(final Object o) {
- if (o == this) {
+ public void setSessionIds(String[] sessionIds) {
+ this.sessionIds = sessionIds;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
return true;
}
- if (!(o instanceof Participant)) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- final Participant other = (Participant) o;
- if (!other.canEqual((Object) this)) {
+
+ Participant that = (Participant) o;
+
+ if (lastPing != that.lastPing) {
return false;
}
- final Object this$userId = this.getUserId();
- final Object other$userId = other.getUserId();
- if (this$userId == null ? other$userId != null : !this$userId.equals(other$userId)) {
+ if (roomId != that.roomId) {
return false;
}
- final Object this$type = this.getType();
- final Object other$type = other.getType();
- if (this$type == null ? other$type != null : !this$type.equals(other$type)) {
+ if (selected != that.selected) {
return false;
}
- final Object this$name = this.getName();
- final Object other$name = other.getName();
- if (this$name == null ? other$name != null : !this$name.equals(other$name)) {
+ if (!attendeeId.equals(that.attendeeId)) {
return false;
}
- final Object this$displayName = this.getDisplayName();
- final Object other$displayName = other.getDisplayName();
- if (this$displayName == null ? other$displayName != null : !this$displayName.equals(other$displayName)) {
+ if (!actorType.equals(that.actorType)) {
return false;
}
- if (this.getLastPing() != other.getLastPing()) {
+ if (!actorId.equals(that.actorId)) {
return false;
}
- final Object this$sessionId = this.getSessionId();
- final Object other$sessionId = other.getSessionId();
- if (this$sessionId == null ? other$sessionId != null : !this$sessionId.equals(other$sessionId)) {
+ if (!attendeePin.equals(that.attendeePin)) {
return false;
}
- if (this.getRoomId() != other.getRoomId()) {
+ if (!userId.equals(that.userId)) {
return false;
}
- final Object this$inCall = this.getInCall();
- final Object other$inCall = other.getInCall();
- if (this$inCall == null ? other$inCall != null : !this$inCall.equals(other$inCall)) {
+ if (type != that.type) {
return false;
}
- final Object this$source = this.getSource();
- final Object other$source = other.getSource();
- if (this$source == null ? other$source != null : !this$source.equals(other$source)) {
+ if (!name.equals(that.name)) {
return false;
}
-
- return this.isSelected() == other.isSelected();
+ if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) {
+ return false;
+ }
+ if (!sessionId.equals(that.sessionId)) {
+ return false;
+ }
+ // Probably incorrect - comparing Object[] arrays with Arrays.equals
+ if (!Arrays.equals(sessionIds, that.sessionIds)) {
+ return false;
+ }
+ if (inCall != null ? !inCall.equals(that.inCall) : that.inCall != null) {
+ return false;
+ }
+ return source != null ? source.equals(that.source) : that.source == null;
}
protected boolean canEqual(final Object other) {
return other instanceof Participant;
}
+ @Override
public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- final Object $userId = this.getUserId();
- result = result * PRIME + ($userId == null ? 43 : $userId.hashCode());
- final Object $type = this.getType();
- result = result * PRIME + ($type == null ? 43 : $type.hashCode());
- final Object $name = this.getName();
- result = result * PRIME + ($name == null ? 43 : $name.hashCode());
- final Object $displayName = this.getDisplayName();
- result = result * PRIME + ($displayName == null ? 43 : $displayName.hashCode());
- final long $lastPing = this.getLastPing();
- result = result * PRIME + (int) ($lastPing >>> 32 ^ $lastPing);
- final Object $sessionId = this.getSessionId();
- result = result * PRIME + ($sessionId == null ? 43 : $sessionId.hashCode());
- final long $roomId = this.getRoomId();
- result = result * PRIME + (int) ($roomId >>> 32 ^ $roomId);
- final Object $inCall = this.getInCall();
- result = result * PRIME + ($inCall == null ? 43 : $inCall.hashCode());
- final Object $source = this.getSource();
- result = result * PRIME + ($source == null ? 43 : $source.hashCode());
- result = result * PRIME + (this.isSelected() ? 79 : 97);
+ int result = (attendeeId != null ? attendeeId.hashCode() : 0);
+ result = 31 * result + (actorType != null ? actorType.hashCode() : 0);
+ result = 31 * result + (actorId != null ? actorId.hashCode() : 0);
+ result = 31 * result + (attendeePin != null ? attendeePin.hashCode() : 0);
+ result = 31 * result + (userId != null ? userId.hashCode() : 0);
+ result = 31 * result + (type != null ? type.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
+ result = 31 * result + (int) (lastPing ^ (lastPing >>> 32));
+ result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
+ result = 31 * result + Arrays.hashCode(sessionIds);
+ result = 31 * result + (int) (roomId ^ (roomId >>> 32));
+ result = 31 * result + (inCall != null ? inCall.hashCode() : 0);
+ result = 31 * result + (source != null ? source.hashCode() : 0);
+ result = 31 * result + (selected ? 1 : 0);
return result;
}
+ @Override
public String toString() {
- return "Participant(userId=" + this.getUserId() + ", type=" + this.getType() + ", name=" + this.getName() + ", displayName=" + this.getDisplayName() + ", lastPing=" + this.getLastPing() + ", sessionId=" + this.getSessionId() + ", roomId=" + this.getRoomId() + ", inCall=" + this.getInCall() + ", source=" + this.getSource() + ", selected=" + this.isSelected() + ")";
+ return "Participant{" +
+ "attendeeId=" + attendeeId +
+ ", actorType='" + actorType + '\'' +
+ ", actorId='" + actorId + '\'' +
+ ", attendeePin='" + attendeePin + '\'' +
+ ", userId='" + userId + '\'' +
+ ", type=" + type +
+ ", name='" + name + '\'' +
+ ", displayName='" + displayName + '\'' +
+ ", lastPing=" + lastPing +
+ ", sessionId='" + sessionId + '\'' +
+ ", sessionIds=" + Arrays.toString(sessionIds) +
+ ", roomId=" + roomId +
+ ", inCall=" + inCall +
+ ", source='" + source + '\'' +
+ ", selected=" + selected +
+ '}';
+ }
+
+ public enum ActorType {
+ DUMMY,
+ EMAILS,
+ GROUPS,
+ GUESTS,
+ USERS,
}
public enum ParticipantType {
diff --git a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
index 8a037c951..c9e75f1af 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
@@ -111,6 +111,10 @@ public class ApiUtils {
return baseUrl + ocsApiVersion + "/cloud/capabilities";
}
+ public static int getCallApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
+ return getConversationApiVersion(capabilities, versions);
+ }
+
public static int getConversationApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
boolean hasApiV4 = false;
for (int version : versions) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5848fbf86..0d6942d3b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -255,6 +255,8 @@
<string name="nc_demote">Demote from moderator</string>
<string name="nc_promote">Promote to moderator</string>
<string name="nc_remove_participant">Remove participant</string>
+ <string name="nc_remove_group_and_members">Remove group and members</string>
+ <string name="nc_attendee_pin">Pin: %1$s</string>
<!-- Chat -->
<string name="nc_hint_enter_a_message">Enter a messageā€¦</string>
@@ -305,6 +307,8 @@
<!-- Other -->
<string name="nc_limit_hit">%s characters limit has been hit</string>
+ <string name="nc_email">Email</string>
+ <string name="nc_group">Group</string>
<string name="nc_groups">Groups</string>
<string name="nc_participants">Participants</string>
<string name="nc_participants_add">Add participants</string>