Merge pull request #1225 from nextcloud/feature/apiv4/fix-participant-list

[apiv4] 👥 Fix participant list
This commit is contained in:
Andy Scherzinger 2021-05-09 19:20:21 +02:00 committed by GitHub
commit 16255b885f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 784 additions and 417 deletions

View File

@ -21,6 +21,7 @@
package com.nextcloud.talk.adapters.items; package com.nextcloud.talk.adapters.items;
import android.accounts.Account; import android.accounts.Account;
import android.net.Uri;
import android.view.View; import android.view.View;
import android.widget.*; import android.widget.*;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -106,14 +107,14 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
holder.avatarImageView.setController(null); holder.avatarImageView.setController(null);
if (adapter.hasFilter()) { if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, participant.getName(), FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication() String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary)); .getResources().getColor(R.color.colorPrimary));
} else { } 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://")) { if (userEntity != null && userEntity.getBaseUrl() != null && userEntity.getBaseUrl().startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
holder.avatarImageView.setVisibility(View.VISIBLE); holder.avatarImageView.setVisibility(View.VISIBLE);
@ -122,7 +123,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
.setOldController(holder.avatarImageView.getController()) .setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true) .setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), null)) participant.getActorId(), R.dimen.avatar_size), null))
.build(); .build();
holder.avatarImageView.setController(draweeController); holder.avatarImageView.setController(draweeController);
@ -138,8 +139,8 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
@Override @Override
public boolean filter(String constraint) { public boolean filter(String constraint) {
return participant.getName() != null && return participant.getDisplayName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getName().trim()).find(); Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getDisplayName().trim()).find();
} }

View File

@ -21,7 +21,6 @@
package com.nextcloud.talk.adapters.items; package com.nextcloud.talk.adapters.items;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
@ -150,9 +149,15 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)); holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest));
} }
if (TextUtils.isEmpty(participant.getSource()) || participant.getSource().equals("users")) { if (participant.getActorType() == Participant.ActorType.GROUPS || "groups".equals(participant.getSource())) {
if (Participant.ParticipantType.GUEST.equals(participant.getType()) || holder.simpleDraweeView.setImageResource(R.drawable.ic_circular_group);
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participant.getType())) { } 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())) {
String displayName = NextcloudTalkApplication.Companion.getSharedApplication() String displayName = NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getString(R.string.nc_guest); .getResources().getString(R.string.nc_guest);
@ -168,8 +173,7 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
.build(); .build();
holder.simpleDraweeView.setController(draweeController); holder.simpleDraweeView.setController(draweeController);
} else { } else if (participant.getActorType() == Participant.ActorType.USERS || participant.getSource().equals("users")) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder() DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController()) .setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true) .setAutoPlayAnimations(true)
@ -177,10 +181,6 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
participant.getUserId(), R.dimen.avatar_size), null)) participant.getUserId(), R.dimen.avatar_size), null))
.build(); .build();
holder.simpleDraweeView.setController(draweeController); holder.simpleDraweeView.setController(draweeController);
}
} else if ("groups".equals(participant.getSource())) {
holder.simpleDraweeView.setImageResource(R.drawable.ic_circular_group);
} }
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources(); 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); //userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner);
//break; //break;
case 2: case 2:
case 6: // Guest moderator
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator); userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator);
break; break;
case 3: case 3:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user); 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; break;
case 4: case 4:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest); 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; break;
case 5: case 5:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link); userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link);

View File

@ -135,15 +135,27 @@ public interface NcApi {
// also used for removing a guest from a conversation // also used for removing a guest from a conversation
@Deprecated
@DELETE @DELETE
Observable<GenericOverall> removeParticipantFromConversation(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId); 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 @POST
Observable<GenericOverall> promoteUserToModerator(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId); Observable<GenericOverall> promoteUserToModerator(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
@Deprecated
@DELETE @DELETE
Observable<GenericOverall> demoteModeratorToUser(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId); 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 Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/participants/self
*/ */

View File

@ -1273,7 +1273,7 @@ public class CallController extends BaseController {
inCallFlag = (int) Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue(); 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) ncApi.joinCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken), inCallFlag)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -1558,7 +1558,7 @@ public class CallController extends BaseController {
} }
private void hangupNetworkCalls(boolean shutDownView) { 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)) ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -1686,7 +1686,7 @@ public class CallController extends BaseController {
private void getPeersForCall() { private void getPeersForCall() {
Log.d(TAG, "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)) ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View File

@ -209,7 +209,7 @@ public class CallNotificationController extends BaseController {
} }
private void checkIfAnyParticipantsRemainInRoom() { 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(), ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, userBeingCalled.getBaseUrl(),
currentConversation.getToken())) currentConversation.getToken()))

View File

@ -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.autocomplete.AutocompleteUser;
import com.nextcloud.talk.models.json.conversations.Conversation; import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomOverall; 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.models.json.participants.Participant;
import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.ConductorRemapping; import com.nextcloud.talk.utils.ConductorRemapping;
@ -508,6 +509,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
Participant participant; Participant participant;
List<AbstractFlexibleItem> newUserItemList = new ArrayList<>(); List<AbstractFlexibleItem> newUserItemList = new ArrayList<>();
EnumActorTypeConverter actorTypeConverter = new EnumActorTypeConverter();
try { try {
AutocompleteOverall autocompleteOverall = LoganSquare.parse(responseBody.string(), AutocompleteOverall.class); AutocompleteOverall autocompleteOverall = LoganSquare.parse(responseBody.string(), AutocompleteOverall.class);
@ -516,13 +518,14 @@ public class ContactsController extends BaseController implements SearchView.OnQ
for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) { for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) {
if (!autocompleteUser.getId().equals(currentUser.getUserId()) && !existingParticipants.contains(autocompleteUser.getId())) { if (!autocompleteUser.getId().equals(currentUser.getUserId()) && !existingParticipants.contains(autocompleteUser.getId())) {
participant = new Participant(); participant = new Participant();
participant.setUserId(autocompleteUser.getId()); participant.setActorId(autocompleteUser.getId());
participant.setActorType(actorTypeConverter.getFromString(autocompleteUser.getSource()));
participant.setDisplayName(autocompleteUser.getLabel()); participant.setDisplayName(autocompleteUser.getLabel());
participant.setSource(autocompleteUser.getSource()); participant.setSource(autocompleteUser.getSource());
String headerTitle; String headerTitle;
if (!autocompleteUser.getSource().equals("groups")) { if (participant.getActorType() != Participant.ActorType.GROUPS) {
headerTitle = participant.getDisplayName().substring(0, 1).toUpperCase(); headerTitle = participant.getDisplayName().substring(0, 1).toUpperCase();
} else { } else {
headerTitle = getResources().getString(R.string.nc_groups); headerTitle = getResources().getString(R.string.nc_groups);

View File

@ -20,11 +20,13 @@
package com.nextcloud.talk.controllers package com.nextcloud.talk.controllers
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View 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.converters.EnumNotificationLevelConverter
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.participants.Participant 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.models.json.participants.ParticipantsOverall
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
@ -410,8 +414,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
for (i in participants.indices) { for (i in participants.indices) {
participant = participants[i] participant = participants[i]
userItem = UserItem(participant, conversationUser, null) userItem = UserItem(participant, conversationUser, null)
if (participant.sessionId != null) {
userItem.isOnline = !participant.sessionId.equals("0") userItem.isOnline = !participant.sessionId.equals("0")
if (!TextUtils.isEmpty(participant.userId) && participant.userId == conversationUser!!.userId) { } else {
userItem.isOnline = !participant.sessionIds!!.isEmpty()
}
if (participant.getActorType() == USERS && participant.getActorId() == conversationUser!!.userId) {
ownUserItem = userItem ownUserItem = userItem
ownUserItem.model.sessionId = "-1" ownUserItem.model.sessionId = "-1"
ownUserItem.isOnline = true ownUserItem.isOnline = true
@ -444,7 +453,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
var apiVersion = 1 var apiVersion = 1
// FIXME Fix API checking with guests? // FIXME Fix API checking with guests?
if (conversationUser != null) { if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1)) apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
} }
ncApi.getPeersForCall( ncApi.getPeersForCall(
@ -478,7 +487,9 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
recyclerViewItems.forEach { recyclerViewItems.forEach {
val userItem = it as UserItem 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) bundle.putBoolean(BundleKeys.KEY_ADD_PARTICIPANTS, true)
@ -572,7 +583,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
leaveConversationAction.visibility = View.VISIBLE leaveConversationAction.visibility = View.VISIBLE
} }
if (!conversation!!.canModerate(conversationUser)) { if (!conversation!!.canDelete(conversationUser)) {
deleteConversationAction.visibility = View.GONE deleteConversationAction.visibility = View.GONE
} else { } else {
deleteConversationAction.visibility = View.VISIBLE deleteConversationAction.visibility = View.VISIBLE
@ -685,12 +696,258 @@ 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 { override fun onItemClick(view: View?, position: Int): Boolean {
if (!conversation!!.canModerate(conversationUser)) {
return true
}
val userItem = adapter?.getItem(position) as UserItem val userItem = adapter?.getItem(position) as UserItem
val participant = userItem.model val participant = userItem.model
if (participant.userId != conversationUser!!.userId) { 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_group_and_members)
)
)
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
}
var items = mutableListOf( 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_promote)),
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)), BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
BasicListItemWithImage( BasicListItemWithImage(
@ -699,14 +956,22 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
) )
) )
if (!conversation!!.canModerate(conversationUser)) { if (participant.type == Participant.ParticipantType.MODERATOR ||
items = mutableListOf() 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 { } else {
if (participant.type == Participant.ParticipantType.MODERATOR || participant.type == Participant.ParticipantType.OWNER) { // Self joined users can not be promoted nor demoted
items.removeAt(0) items.removeAt(2)
} else if (participant.type == Participant.ParticipantType.USER) {
items.removeAt(1) items.removeAt(1)
} }
if (participant.attendeePin.isEmpty()) {
items.removeAt(0)
} }
if (items.isNotEmpty()) { if (items.isNotEmpty()) {
@ -715,87 +980,36 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
title(text = participant.displayName) title(text = participant.displayName)
listItemsWithImage(items = items) { dialog, index, _ -> listItemsWithImage(items = items) { dialog, index, _ ->
var actionToTrigger = index
if (participant.attendeePin.isEmpty()) {
actionToTrigger++
}
if (participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK) {
actionToTrigger++
}
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1)) if (actionToTrigger == 0) {
// Pin, nothing to do
if (index == 0) { } else if (actionToTrigger == 1) {
if (participant.type == Participant.ParticipantType.MODERATOR) { // Promote/demote
ncApi.demoteModeratorToUser( if (apiVersion >= ApiUtils.APIv4) {
credentials, toggleModeratorStatus(apiVersion, participant)
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 { } else {
ncApi.removeParticipantFromConversation( toggleModeratorStatusLegacy(apiVersion, participant)
credentials, }
ApiUtils.getUrlForRemovingParticipantFromConversation( } else if (actionToTrigger == 2) {
conversationUser.baseUrl, // Remove from conversation
conversation!!.token, removeAttendeeFromConversation(apiVersion, participant)
false
),
participant.userId
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
getListOfParticipants()
// get participants again
} }
} }
} }
} }
}
}
}
return true return true
} }
companion object { companion object {
private const val TAG = "ConversationInfoController"
private const val ID_DELETE_CONVERSATION_DIALOG = 0 private const val ID_DELETE_CONVERSATION_DIALOG = 0
} }
@ -804,6 +1018,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
*/ */
class UserItemComparator : Comparator<UserItem> { class UserItemComparator : Comparator<UserItem> {
override fun compare(left: UserItem, right: UserItem): Int { 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) { if (left.isOnline && !right.isOnline) {
return -1 return -1
} else if (!left.isOnline && right.isOnline) { } else if (!left.isOnline && right.isOnline) {

View File

@ -178,17 +178,17 @@ public class SwitchAccountController extends BaseController {
for (Object userEntityObject : userUtils.getUsers()) { for (Object userEntityObject : userUtils.getUsers()) {
userEntity = (UserEntity) userEntityObject; userEntity = (UserEntity) userEntityObject;
if (!userEntity.getCurrent()) { if (!userEntity.getCurrent()) {
participant = new Participant();
participant.setName(userEntity.getDisplayName());
String userId; String userId;
if (userEntity.getUserId() != null) { if (userEntity.getUserId() != null) {
userId = userEntity.getUserId(); userId = userEntity.getUserId();
} else { } else {
userId = userEntity.getUsername(); 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)); userItems.add(new AdvancedUserItem(participant, userEntity, null));
} }
} }
@ -203,8 +203,9 @@ public class SwitchAccountController extends BaseController {
importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account); importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
participant = new Participant(); participant = new Participant();
participant.setName(importAccount.getUsername()); participant.setActorType(Participant.ActorType.USERS);
participant.setUserId(importAccount.getUsername()); participant.setActorId(importAccount.getUsername());
participant.setDisplayName(importAccount.getUsername());
userEntity = new UserEntity(); userEntity = new UserEntity();
userEntity.setBaseUrl(importAccount.getBaseUrl()); userEntity.setBaseUrl(importAccount.getBaseUrl());
userItems.add(new AdvancedUserItem(participant, userEntity, account)); userItems.add(new AdvancedUserItem(participant, userEntity, account));

View File

@ -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.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.models.json.conversations.Conversation; import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomOverall; 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.models.json.participants.AddParticipantOverall;
import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.ConductorRemapping; import com.nextcloud.talk.utils.ConductorRemapping;
@ -270,29 +269,20 @@ public class OperationsMenuController extends BaseController {
break; break;
case 11: case 11:
RetrofitBucket retrofitBucket; RetrofitBucket retrofitBucket;
boolean isGroupCallWorkaround = false;
String invite = null; String invite = null;
if (invitedGroups.size() > 0) { if (invitedGroups.size() > 0) {
invite = invitedGroups.get(0); invite = invitedGroups.get(0);
} }
if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) || if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL)) {
!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(), retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
"3", invite, conversationName); "3", invite, conversationName);
} else { } else {
String roomType = "2";
if (!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
isGroupCallWorkaround = true;
roomType = "3";
}
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(), retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
roomType, invite, conversationName); "2", invite, conversationName);
} }
final boolean isGroupCallWorkaroundFinal = isGroupCallWorkaround;
ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -321,12 +311,8 @@ public class OperationsMenuController extends BaseController {
@Override @Override
public void onNext(RoomOverall roomOverall) { public void onNext(RoomOverall roomOverall) {
conversation = roomOverall.getOcs().getData(); conversation = roomOverall.getOcs().getData();
if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) && isGroupCallWorkaroundFinal) {
performGroupCallWorkaround(credentials);
} else {
inviteUsersToAConversation(); inviteUsersToAConversation();
} }
}
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
@ -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) { private void showResultImage(boolean everythingOK, boolean isGuestSupportError) {
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
@ -552,7 +504,7 @@ public class OperationsMenuController extends BaseController {
localInvitedGroups.remove(0); 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 (localInvitedUsers.size() > 0 || (localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) {
if ((localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) { if ((localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) {

View File

@ -66,7 +66,7 @@ public class AddParticipantsToConversation extends Worker {
String[] selectedGroupIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_GROUPS()); String[] selectedGroupIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_GROUPS());
UserEntity user = userUtils.getUserWithInternalId(data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1)); 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 conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken()); String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken());

View File

@ -84,9 +84,13 @@ public class Conversation {
public int lastReadMessage; public int lastReadMessage;
@JsonField(name = "callFlag") @JsonField(name = "callFlag")
public int callFlag; public int callFlag;
@JsonField(name = "canLeaveConversation") @JsonField(name = "canLeaveConversation")
public Boolean canLeaveConversation; public Boolean canLeaveConversation;
@JsonField(name = "canDeleteConversation")
public Boolean canDeleteConversation;
public boolean isPublic() { public boolean isPublic() {
return (ConversationType.ROOM_PUBLIC_CALL.equals(type)); 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); (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() { public String getRoomId() {
return this.roomId; return this.roomId;
} }
@ -314,169 +327,155 @@ public class Conversation {
this.callFlag = callFlag; this.callFlag = callFlag;
} }
public boolean equals(final Object o) { @Override
if (o == this) { public boolean equals(Object o) {
if (this == o) {
return true; return true;
} }
if (!(o instanceof Conversation)) { if (o == null || getClass() != o.getClass()) {
return false;
}
final Conversation other = (Conversation) o;
if (!other.canEqual((Object) this)) {
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)) {
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$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) {
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)) {
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)) {
return false;
}
if (this.getLastPing() != other.getLastPing()) {
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)) {
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)) {
return false;
}
if (this.isHasPassword() != other.isHasPassword()) {
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)) {
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)) {
return false;
}
if (this.isFavorite() != other.isFavorite()) {
return false;
}
if (this.getLastActivity() != other.getLastActivity()) {
return false;
}
if (this.getUnreadMessages() != other.getUnreadMessages()) {
return false;
}
if (this.isUnreadMention() != other.isUnreadMention()) {
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)) {
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)) {
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)) {
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)) {
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)) {
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)) {
return false;
}
if (this.getLastReadMessage() != other.getLastReadMessage()) {
return false; return false;
} }
return this.getCallFlag() == other.getCallFlag(); 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 (callFlag != that.callFlag) {
return false;
}
if (roomId != null ? !roomId.equals(that.roomId) : that.roomId != null) {
return false;
}
if (!token.equals(that.token)) {
return false;
}
if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) {
return false;
}
if (type != that.type) {
return false;
}
if (participants != null ? !participants.equals(that.participants) : that.participants != null) {
return false;
}
if (participantType != that.participantType) {
return false;
}
if (sessionId != null ? !sessionId.equals(that.sessionId) : that.sessionId != null) {
return false;
}
if (password != null ? !password.equals(that.password) : that.password != null) {
return false;
}
if (lastMessage != null ? !lastMessage.equals(that.lastMessage) : that.lastMessage != null) {
return false;
}
if (objectType != null ? !objectType.equals(that.objectType) : that.objectType != null) {
return false;
}
if (notificationLevel != that.notificationLevel) {
return false;
}
if (conversationReadOnlyState != that.conversationReadOnlyState) {
return false;
}
if (lobbyState != that.lobbyState) {
return false;
}
if (lobbyTimer != null ? !lobbyTimer.equals(that.lobbyTimer) : that.lobbyTimer != null) {
return false;
}
if (canLeaveConversation != null ? !canLeaveConversation.equals(that.canLeaveConversation) : that.canLeaveConversation != null) {
return false;
}
return canDeleteConversation != null ? canDeleteConversation.equals(that.canDeleteConversation) : that.canDeleteConversation == null;
} }
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof Conversation; return other instanceof Conversation;
} }
@Override
public int hashCode() { public int hashCode() {
final int PRIME = 59; int result = roomId != null ? roomId.hashCode() : 0;
int result = 1; result = 31 * result + token.hashCode();
final Object $roomId = this.getRoomId(); result = 31 * result + (name != null ? name.hashCode() : 0);
result = result * PRIME + ($roomId == null ? 43 : $roomId.hashCode()); result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
final Object $token = this.getToken(); result = 31 * result + type.hashCode();
result = result * PRIME + ($token == null ? 43 : $token.hashCode()); result = 31 * result + (int) (lastPing ^ (lastPing >>> 32));
final Object $name = this.getName(); result = 31 * result + (participants != null ? participants.hashCode() : 0);
result = result * PRIME + ($name == null ? 43 : $name.hashCode()); result = 31 * result + (participantType != null ? participantType.hashCode() : 0);
final Object $displayName = this.getDisplayName(); result = 31 * result + (hasPassword ? 1 : 0);
result = result * PRIME + ($displayName == null ? 43 : $displayName.hashCode()); result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
final Object $type = this.getType(); result = 31 * result + (password != null ? password.hashCode() : 0);
result = result * PRIME + ($type == null ? 43 : $type.hashCode()); result = 31 * result + (isFavorite ? 1 : 0);
final long $lastPing = this.getLastPing(); result = 31 * result + (int) (lastActivity ^ (lastActivity >>> 32));
result = result * PRIME + (int) ($lastPing >>> 32 ^ $lastPing); result = 31 * result + unreadMessages;
final Object $participants = this.participants; result = 31 * result + (unreadMention ? 1 : 0);
result = result * PRIME + ($participants == null ? 43 : $participants.hashCode()); result = 31 * result + (lastMessage != null ? lastMessage.hashCode() : 0);
final Object $participantType = this.getParticipantType(); result = 31 * result + (objectType != null ? objectType.hashCode() : 0);
result = result * PRIME + ($participantType == null ? 43 : $participantType.hashCode()); result = 31 * result + (notificationLevel != null ? notificationLevel.hashCode() : 0);
result = result * PRIME + (this.isHasPassword() ? 79 : 97); result = 31 * result + (conversationReadOnlyState != null ? conversationReadOnlyState.hashCode() : 0);
final Object $sessionId = this.getSessionId(); result = 31 * result + (lobbyState != null ? lobbyState.hashCode() : 0);
result = result * PRIME + ($sessionId == null ? 43 : $sessionId.hashCode()); result = 31 * result + (lobbyTimer != null ? lobbyTimer.hashCode() : 0);
final Object $password = this.getPassword(); result = 31 * result + lastReadMessage;
result = result * PRIME + ($password == null ? 43 : $password.hashCode()); result = 31 * result + callFlag;
result = result * PRIME + (this.isFavorite() ? 79 : 97); result = 31 * result + (canLeaveConversation != null ? canLeaveConversation.hashCode() : 0);
final long $lastActivity = this.getLastActivity(); result = 31 * result + (canDeleteConversation != null ? canDeleteConversation.hashCode() : 0);
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();
return result; return result;
} }
@Override
public String toString() { 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 { public enum NotificationLevel {

View File

@ -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 -> ""
}
}
}

View File

@ -22,21 +22,38 @@ package com.nextcloud.talk.models.json.participants;
import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject; 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.EnumParticipantTypeConverter;
import com.nextcloud.talk.models.json.converters.ObjectParcelConverter; import com.nextcloud.talk.models.json.converters.ObjectParcelConverter;
import org.parceler.Parcel; import org.parceler.Parcel;
import org.parceler.ParcelPropertyConverter; import org.parceler.ParcelPropertyConverter;
import java.util.Arrays;
@Parcel @Parcel
@JsonObject @JsonObject
public class Participant { 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") @JsonField(name = "userId")
public String userId; public String userId;
@JsonField(name = {"type", "participantType"}, typeConverter = EnumParticipantTypeConverter.class) @JsonField(name = {"type", "participantType"}, typeConverter = EnumParticipantTypeConverter.class)
public ParticipantType type; public ParticipantType type;
@Deprecated
@JsonField(name = "name") @JsonField(name = "name")
public String name; public String name;
@ -46,15 +63,21 @@ public class Participant {
@JsonField(name = "lastPing") @JsonField(name = "lastPing")
public long lastPing; public long lastPing;
@Deprecated
@JsonField(name = "sessionId") @JsonField(name = "sessionId")
public String sessionId; public String sessionId;
@JsonField(name = "sessionIds")
public String[] sessionIds;
@Deprecated
@JsonField(name = "roomId") @JsonField(name = "roomId")
public long roomId; public long roomId;
@ParcelPropertyConverter(ObjectParcelConverter.class) @ParcelPropertyConverter(ObjectParcelConverter.class)
@JsonField(name = "inCall") @JsonField(name = "inCall")
public Object inCall; public Object inCall;
public String source; public String source;
public boolean selected; public boolean selected;
@ -76,7 +99,37 @@ public class Participant {
return participantFlags; 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() { public String getUserId() {
if (this.actorType != null && this.actorType == ActorType.USERS) {
return this.actorId;
}
return this.userId; return this.userId;
} }
@ -84,6 +137,7 @@ public class Participant {
return this.type; return this.type;
} }
@Deprecated
public String getName() { public String getName() {
return this.name; return this.name;
} }
@ -96,10 +150,16 @@ public class Participant {
return this.lastPing; return this.lastPing;
} }
@Deprecated
public String getSessionId() { public String getSessionId() {
return this.sessionId; return this.sessionId;
} }
public String[] getSessionIds() {
return sessionIds;
}
@Deprecated
public long getRoomId() { public long getRoomId() {
return this.roomId; return this.roomId;
} }
@ -116,14 +176,32 @@ public class Participant {
return this.selected; return this.selected;
} }
@Deprecated
public void setUserId(String userId) { public void setUserId(String userId) {
this.userId = 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) { public void setType(ParticipantType type) {
this.type = type; this.type = type;
} }
@Deprecated
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@ -136,10 +214,12 @@ public class Participant {
this.lastPing = lastPing; this.lastPing = lastPing;
} }
@Deprecated
public void setSessionId(String sessionId) { public void setSessionId(String sessionId) {
this.sessionId = sessionId; this.sessionId = sessionId;
} }
@Deprecated
public void setRoomId(long roomId) { public void setRoomId(long roomId) {
this.roomId = roomId; this.roomId = roomId;
} }
@ -156,93 +236,118 @@ public class Participant {
this.selected = selected; this.selected = selected;
} }
public boolean equals(final Object o) { public void setSessionIds(String[] sessionIds) {
if (o == this) { this.sessionIds = sessionIds;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true; return true;
} }
if (!(o instanceof Participant)) { if (o == null || getClass() != o.getClass()) {
return false;
}
final Participant other = (Participant) o;
if (!other.canEqual((Object) this)) {
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)) {
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)) {
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)) {
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)) {
return false;
}
if (this.getLastPing() != other.getLastPing()) {
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)) {
return false;
}
if (this.getRoomId() != other.getRoomId()) {
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)) {
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)) {
return false; return false;
} }
return this.isSelected() == other.isSelected(); Participant that = (Participant) o;
if (lastPing != that.lastPing) {
return false;
}
if (roomId != that.roomId) {
return false;
}
if (selected != that.selected) {
return false;
}
if (!attendeeId.equals(that.attendeeId)) {
return false;
}
if (!actorType.equals(that.actorType)) {
return false;
}
if (!actorId.equals(that.actorId)) {
return false;
}
if (!attendeePin.equals(that.attendeePin)) {
return false;
}
if (!userId.equals(that.userId)) {
return false;
}
if (type != that.type) {
return false;
}
if (!name.equals(that.name)) {
return false;
}
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) { protected boolean canEqual(final Object other) {
return other instanceof Participant; return other instanceof Participant;
} }
@Override
public int hashCode() { public int hashCode() {
final int PRIME = 59; int result = (attendeeId != null ? attendeeId.hashCode() : 0);
int result = 1; result = 31 * result + (actorType != null ? actorType.hashCode() : 0);
final Object $userId = this.getUserId(); result = 31 * result + (actorId != null ? actorId.hashCode() : 0);
result = result * PRIME + ($userId == null ? 43 : $userId.hashCode()); result = 31 * result + (attendeePin != null ? attendeePin.hashCode() : 0);
final Object $type = this.getType(); result = 31 * result + (userId != null ? userId.hashCode() : 0);
result = result * PRIME + ($type == null ? 43 : $type.hashCode()); result = 31 * result + (type != null ? type.hashCode() : 0);
final Object $name = this.getName(); result = 31 * result + (name != null ? name.hashCode() : 0);
result = result * PRIME + ($name == null ? 43 : $name.hashCode()); result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
final Object $displayName = this.getDisplayName(); result = 31 * result + (int) (lastPing ^ (lastPing >>> 32));
result = result * PRIME + ($displayName == null ? 43 : $displayName.hashCode()); result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
final long $lastPing = this.getLastPing(); result = 31 * result + Arrays.hashCode(sessionIds);
result = result * PRIME + (int) ($lastPing >>> 32 ^ $lastPing); result = 31 * result + (int) (roomId ^ (roomId >>> 32));
final Object $sessionId = this.getSessionId(); result = 31 * result + (inCall != null ? inCall.hashCode() : 0);
result = result * PRIME + ($sessionId == null ? 43 : $sessionId.hashCode()); result = 31 * result + (source != null ? source.hashCode() : 0);
final long $roomId = this.getRoomId(); result = 31 * result + (selected ? 1 : 0);
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);
return result; return result;
} }
@Override
public String toString() { 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 { public enum ParticipantType {

View File

@ -111,6 +111,10 @@ public class ApiUtils {
return baseUrl + ocsApiVersion + "/cloud/capabilities"; 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 { public static int getConversationApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
boolean hasApiV4 = false; boolean hasApiV4 = false;
for (int version : versions) { for (int version : versions) {

View File

@ -255,6 +255,8 @@
<string name="nc_demote">Demote from moderator</string> <string name="nc_demote">Demote from moderator</string>
<string name="nc_promote">Promote to moderator</string> <string name="nc_promote">Promote to moderator</string>
<string name="nc_remove_participant">Remove participant</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 --> <!-- Chat -->
<string name="nc_hint_enter_a_message">Enter a message…</string> <string name="nc_hint_enter_a_message">Enter a message…</string>
@ -305,6 +307,8 @@
<!-- Other --> <!-- Other -->
<string name="nc_limit_hit">%s characters limit has been hit</string> <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_groups">Groups</string>
<string name="nc_participants">Participants</string> <string name="nc_participants">Participants</string>
<string name="nc_participants_add">Add participants</string> <string name="nc_participants_add">Add participants</string>

View File

@ -1 +1 @@
476 475