Merge pull request #1156 from nextcloud/techdebt/noid/api-v4-compatibility

v4️⃣ - Add option for APIv4 compatibility
This commit is contained in:
Joas Schilling 2021-05-07 15:52:48 +02:00 committed by GitHub
commit 6434630709
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 455 additions and 217 deletions

View File

@ -302,9 +302,12 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
var hasParticipantsInCall = false var hasParticipantsInCall = false
var inCallOnDifferentDevice = false var inCallOnDifferentDevice = false
val apiVersion = ApiUtils.getConversationApiVersion(signatureVerification.userEntity, intArrayOf(1))
ncApi.getPeersForCall( ncApi.getPeersForCall(
ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token), ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token),
ApiUtils.getUrlForCall( ApiUtils.getUrlForCall(
apiVersion,
signatureVerification.userEntity.baseUrl, signatureVerification.userEntity.baseUrl,
decryptedPushMessage.id decryptedPushMessage.id
) )

View File

@ -229,9 +229,10 @@ class MainActivity : BaseActivity(), ActionBarProvider {
val roomType = "1" val roomType = "1"
val currentUser = userUtils.currentUser ?: return val currentUser = userUtils.currentUser ?: return
val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(1))
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token) val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom( val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
currentUser.baseUrl, roomType, apiVersion, currentUser.baseUrl, roomType,
userId, null userId, null
) )
ncApi.createRoom( ncApi.createRoom(
@ -251,7 +252,8 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (currentUser.hasSpreedFeatureCapability("chat-v2")) { if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
ncApi.getRoom( ncApi.getRoom(
credentials, credentials,
ApiUtils.getRoom( ApiUtils.getUrlForRoom(
apiVersion,
currentUser.baseUrl, currentUser.baseUrl,
roomOverall.ocs.data.token roomOverall.ocs.data.token
) )

View File

@ -46,6 +46,7 @@ import com.nextcloud.talk.jobs.CapabilitiesWorker;
import com.nextcloud.talk.jobs.PushRegistrationWorker; import com.nextcloud.talk.jobs.PushRegistrationWorker;
import com.nextcloud.talk.jobs.SignalingSettingsWorker; import com.nextcloud.talk.jobs.SignalingSettingsWorker;
import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.models.json.generic.Status; import com.nextcloud.talk.models.json.generic.Status;
import com.nextcloud.talk.models.json.conversations.RoomsOverall; import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall; import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
@ -221,17 +222,35 @@ public class AccountVerificationController extends BaseController {
} }
private void findServerTalkApp(String credentials) { private void findServerTalkApp(String credentials) {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl)) ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(new Observer<RoomsOverall>() { .subscribe(new Observer<CapabilitiesOverall>() {
@Override @Override
public void onSubscribe(Disposable d) { public void onSubscribe(Disposable d) {
disposables.add(d); disposables.add(d);
} }
@Override @Override
public void onNext(RoomsOverall roomsOverall) { public void onNext(CapabilitiesOverall capabilitiesOverall) {
boolean hasTalk =
capabilitiesOverall.getOcs().getData().getCapabilities() != null
&& capabilitiesOverall.getOcs().getData().getCapabilities().getSpreedCapability() != null
&& capabilitiesOverall.getOcs().getData().getCapabilities().getSpreedCapability().getFeatures() != null
&& !capabilitiesOverall.getOcs().getData().getCapabilities().getSpreedCapability().getFeatures().isEmpty();
if (hasTalk) {
fetchProfile(credentials); fetchProfile(credentials);
} else {
if (getActivity() != null && getResources() != null) {
getActivity().runOnUiThread(() -> progressText.setText(String.format(getResources().getString(
R.string.nc_nextcloud_talk_app_not_installed), getResources().getString(R.string.nc_app_name))));
}
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK);
abortVerification();
}
} }
@Override @Override

View File

@ -441,7 +441,9 @@ public class CallController extends BaseController {
} }
private void handleFromNotification() { private void handleFromNotification() {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl)) int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl))
.retry(3) .retry(3)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -1097,7 +1099,9 @@ public class CallController extends BaseController {
} }
private void fetchSignalingSettings() { private void fetchSignalingSettings() {
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl)) int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[] {2, 1});
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(apiVersion, baseUrl))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.retry(3) .retry(3)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -1234,9 +1238,11 @@ public class CallController extends BaseController {
private void joinRoomAndCall() { private void joinRoomAndCall() {
callSession = ApplicationWideCurrentRoomHolder.getInstance().getSession(); callSession = ApplicationWideCurrentRoomHolder.getInstance().getSession();
int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
if (TextUtils.isEmpty(callSession)) { if (TextUtils.isEmpty(callSession)) {
ncApi.joinRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion, baseUrl, roomToken),
roomToken), conversationPassword) conversationPassword)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(3) .retry(3)
@ -1288,8 +1294,9 @@ 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();
} }
ncApi.joinCall(credentials, int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
ApiUtils.getUrlForCall(baseUrl, roomToken), inCallFlag)
ncApi.joinCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken), inCallFlag)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.retry(3) .retry(3)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -1349,7 +1356,10 @@ public class CallController extends BaseController {
} }
if (!hasExternalSignalingServer) { if (!hasExternalSignalingServer) {
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken)) int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[] {2, 1});
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(apiVersion,
baseUrl, urlToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.repeatWhen(observable -> observable) .repeatWhen(observable -> observable)
@ -1613,7 +1623,9 @@ public class CallController extends BaseController {
} }
private void hangupNetworkCalls(boolean shutDownView) { private void hangupNetworkCalls(boolean shutDownView) {
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken)) int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<GenericOverall>() { .subscribe(new Observer<GenericOverall>() {
@ -1648,7 +1660,9 @@ public class CallController extends BaseController {
} }
private void leaveRoom(boolean shutDownView) { private void leaveRoom(boolean shutDownView) {
ncApi.leaveRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken)) int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
ncApi.leaveRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<GenericOverall>() { .subscribe(new Observer<GenericOverall>() {
@ -1741,7 +1755,9 @@ public class CallController extends BaseController {
private void getPeersForCall() { private void getPeersForCall() {
Log.d(TAG, "getPeersForCall"); Log.d(TAG, "getPeersForCall");
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken)) int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {1});
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(new Observer<ParticipantsOverall>() { .subscribe(new Observer<ParticipantsOverall>() {
@Override @Override
@ -2045,7 +2061,9 @@ public class CallController extends BaseController {
urlToken = roomToken; urlToken = roomToken;
} }
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken), int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[] {2, 1});
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(apiVersion, baseUrl, urlToken),
strings.toString()) strings.toString())
.retry(3) .retry(3)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View File

@ -209,7 +209,9 @@ public class CallNotificationController extends BaseController {
} }
private void checkIfAnyParticipantsRemainInRoom() { private void checkIfAnyParticipantsRemainInRoom() {
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(userBeingCalled.getBaseUrl(), int apiVersion = ApiUtils.getConversationApiVersion(userBeingCalled, new int[] {1});
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, userBeingCalled.getBaseUrl(),
currentConversation.getToken())) currentConversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.takeWhile(observable -> !leavingScreen) .takeWhile(observable -> !leavingScreen)
@ -258,9 +260,9 @@ public class CallNotificationController extends BaseController {
} }
private void handleFromNotification() { private void handleFromNotification() {
boolean isConversationApiV3 = userBeingCalled.hasSpreedFeatureCapability("conversation-v3"); int apiVersion = ApiUtils.getConversationApiVersion(userBeingCalled, new int[] {4, 3, 1});
if (isConversationApiV3) {
ncApi.getRoom(credentials, ApiUtils.getRoomV3(userBeingCalled.getBaseUrl(), roomId)) ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, userBeingCalled.getBaseUrl(), roomId))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.retry(3) .retry(3)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -275,6 +277,7 @@ public class CallNotificationController extends BaseController {
currentConversation = roomOverall.getOcs().data; currentConversation = roomOverall.getOcs().data;
runAllThings(); runAllThings();
if (apiVersion >= 3) {
boolean hasCallFlags = userBeingCalled.hasSpreedFeatureCapability("conversation-call-flags"); boolean hasCallFlags = userBeingCalled.hasSpreedFeatureCapability("conversation-call-flags");
if (hasCallFlags) { if (hasCallFlags) {
if (isInCallWithVideo(currentConversation.callFlag)) { if (isInCallWithVideo(currentConversation.callFlag)) {
@ -286,38 +289,12 @@ public class CallNotificationController extends BaseController {
} }
} }
} }
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
} else {
ncApi.getRoom(credentials, ApiUtils.getRoom(userBeingCalled.getBaseUrl(), roomId))
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<RoomOverall>() {
@Override
public void onSubscribe(Disposable d) {
disposablesList.add(d);
} }
@SuppressLint("LongLogTag") @SuppressLint("LongLogTag")
@Override
public void onNext(@NotNull RoomOverall roomOverall) {
currentConversation = roomOverall.getOcs().data;
runAllThings();
}
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Log.e(TAG, e.getMessage(), e);
} }
@Override @Override
@ -326,7 +303,6 @@ public class CallNotificationController extends BaseController {
} }
}); });
} }
}
private boolean isInCallWithVideo(int callFlag) { private boolean isInCallWithVideo(int callFlag) {
return (Participant.ParticipantFlags.IN_CALL_WITH_VIDEO.getValue() == callFlag return (Participant.ParticipantFlags.IN_CALL_WITH_VIDEO.getValue() == callFlag

View File

@ -293,7 +293,9 @@ class ChatController(args: Bundle) :
} }
if (conversationUser != null) { if (conversationUser != null) {
ncApi?.getRoom(credentials, ApiUtils.getRoom(conversationUser.baseUrl, roomToken)) val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
ncApi?.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser.baseUrl, roomToken))
?.subscribeOn(Schedulers.io()) ?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<RoomOverall> { ?.subscribe(object : Observer<RoomOverall> {
@ -332,7 +334,13 @@ class ChatController(args: Bundle) :
} }
private fun handleFromNotification() { private fun handleFromNotification() {
ncApi?.getRooms(credentials, ApiUtils.getUrlForGetRooms(conversationUser?.baseUrl)) var apiVersion = 1
// FIXME Can this be called for guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi?.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, conversationUser?.baseUrl))
?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread()) ?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<RoomsOverall> { ?.subscribe(object : Observer<RoomsOverall> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
@ -958,9 +966,16 @@ class ChatController(args: Bundle) :
if (currentConversation == null || TextUtils.isEmpty(currentConversation?.sessionId) || if (currentConversation == null || TextUtils.isEmpty(currentConversation?.sessionId) ||
currentConversation?.sessionId == "0" currentConversation?.sessionId == "0"
) { ) {
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi?.joinRoom( ncApi?.joinRoom(
credentials, credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(conversationUser?.baseUrl, roomToken), roomPassword ApiUtils.getUrlForParticipantsActive(apiVersion, conversationUser?.baseUrl, roomToken),
roomPassword
) )
?.subscribeOn(Schedulers.io()) ?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
@ -1024,9 +1039,16 @@ class ChatController(args: Bundle) :
} }
private fun leaveRoom() { private fun leaveRoom() {
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi?.leaveRoom( ncApi?.leaveRoom(
credentials, credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant( ApiUtils.getUrlForParticipantsActive(
apiVersion,
conversationUser?.baseUrl, conversationUser?.baseUrl,
roomToken roomToken
) )
@ -1107,9 +1129,11 @@ class ChatController(args: Bundle) :
private fun sendMessage(message: CharSequence, replyTo: Int?) { private fun sendMessage(message: CharSequence, replyTo: Int?) {
if (conversationUser != null) { if (conversationUser != null) {
val apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
ncApi!!.sendChatMessage( ncApi!!.sendChatMessage(
credentials, credentials,
ApiUtils.getUrlForChat(conversationUser.baseUrl, roomToken), ApiUtils.getUrlForChat(apiVersion, conversationUser.baseUrl, roomToken),
message, message,
conversationUser.displayName, conversationUser.displayName,
replyTo replyTo
@ -1209,11 +1233,17 @@ class ChatController(args: Bundle) :
} }
if (!wasDetached) { if (!wasDetached) {
var apiVersion = 1
// FIXME this is a best guess, guests would need to get the capabilities themselves
if (conversationUser != null) {
apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
}
if (lookIntoFuture > 0) { if (lookIntoFuture > 0) {
val finalTimeout = timeout val finalTimeout = timeout
ncApi?.pullChatMessages( ncApi?.pullChatMessages(
credentials, credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
) )
?.subscribeOn(Schedulers.io()) ?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
@ -1242,7 +1272,7 @@ class ChatController(args: Bundle) :
} else { } else {
ncApi?.pullChatMessages( ncApi?.pullChatMessages(
credentials, credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
) )
?.subscribeOn(Schedulers.io()) ?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
@ -1632,9 +1662,20 @@ class ChatController(args: Bundle) :
true true
} }
R.id.action_delete_message -> { R.id.action_delete_message -> {
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi?.deleteChatMessage( ncApi?.deleteChatMessage(
credentials, credentials,
ApiUtils.getUrlForMessageDeletion(conversationUser?.baseUrl, roomToken, message?.id) ApiUtils.getUrlForChatMessage(
apiVersion,
conversationUser?.baseUrl,
roomToken,
message?.id
)
)?.subscribeOn(Schedulers.io()) )?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<ChatOverallSingleMessage> { ?.subscribe(object : Observer<ChatOverallSingleMessage> {
@ -1743,8 +1784,15 @@ class ChatController(args: Bundle) :
if (currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL || if (currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL ||
currentConversation?.name != userMentionClickEvent.userId currentConversation?.name != userMentionClickEvent.userId
) { ) {
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom( val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
conversationUser?.baseUrl, "1", apiVersion, conversationUser?.baseUrl, "1",
userMentionClickEvent.userId, null userMentionClickEvent.userId, null
) )

View File

@ -288,8 +288,12 @@ public class ContactsController extends BaseController implements SearchView.OnQ
userId = selectedUserIds.iterator().next(); userId = selectedUserIds.iterator().next();
} }
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(), roomType, int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {1});
userId, null); RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion,
currentUser.getBaseUrl(),
roomType,
userId,
null);
ncApi.createRoom(credentials, ncApi.createRoom(credentials,
retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -310,7 +314,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
if (currentUser.hasSpreedFeatureCapability("chat-v2")) { if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
ncApi.getRoom(credentials, ncApi.getRoom(credentials,
ApiUtils.getRoom(currentUser.getBaseUrl(), ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
roomOverall.getOcs().getData().getToken())) roomOverall.getOcs().getData().getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -848,7 +852,13 @@ public class ContactsController extends BaseController implements SearchView.OnQ
roomType = "2"; roomType = "2";
} }
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(), roomType, userItem.getModel().getUserId(), null); int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {1});
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion,
currentUser.getBaseUrl(),
roomType,
userItem.getModel().getUserId(),
null);
ncApi.createRoom(credentials, ncApi.createRoom(credentials,
retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) retrofitBucket.getUrl(), retrofitBucket.getQueryMap())

View File

@ -306,9 +306,12 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
) as SwitchCompat ) as SwitchCompat
).isChecked ).isChecked
) 1 else 0 ) 1 else 0
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
ncApi.setLobbyForConversation( ncApi.setLobbyForConversation(
ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token), ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token),
ApiUtils.getUrlForLobbyForConversation(conversationUser.baseUrl, conversation!!.token), ApiUtils.getUrlForRoomWebinaryLobby(apiVersion, conversationUser.baseUrl, conversation!!.token),
state, state,
conversation!!.lobbyTimer conversation!!.lobbyTimer
) )
@ -438,9 +441,15 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
} }
private fun getListOfParticipants() { private fun getListOfParticipants() {
var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi.getPeersForCall( ncApi.getPeersForCall(
credentials, credentials,
ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken) ApiUtils.getUrlForParticipants(apiVersion, conversationUser!!.baseUrl, conversationToken)
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -527,7 +536,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
} }
private fun fetchRoomInfo() { private fun fetchRoomInfo() {
ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser!!.baseUrl, conversationToken)) var apiVersion = 1
// FIXME Fix API checking with guests?
if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
}
ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser!!.baseUrl, conversationToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<RoomOverall> { .subscribe(object : Observer<RoomOverall> {
@ -701,11 +716,17 @@ 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, _ ->
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(1))
if (index == 0) { if (index == 0) {
if (participant.type == Participant.ParticipantType.MODERATOR) { if (participant.type == Participant.ParticipantType.MODERATOR) {
ncApi.demoteModeratorToUser( ncApi.demoteModeratorToUser(
credentials, credentials,
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), ApiUtils.getUrlForRoomModerators(
apiVersion,
conversationUser.baseUrl,
conversation!!.token
),
participant.userId participant.userId
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -716,7 +737,11 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
} else if (participant.type == Participant.ParticipantType.USER) { } else if (participant.type == Participant.ParticipantType.USER) {
ncApi.promoteUserToModerator( ncApi.promoteUserToModerator(
credentials, credentials,
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), ApiUtils.getUrlForRoomModerators(
apiVersion,
conversationUser.baseUrl,
conversation!!.token
),
participant.userId participant.userId
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View File

@ -418,7 +418,10 @@ public class ConversationsListController extends BaseController implements Searc
callItems = new ArrayList<>(); callItems = new ArrayList<>();
roomsQueryDisposable = ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(currentUser.getBaseUrl())) int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {4, 1});
roomsQueryDisposable = ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion,
currentUser.getBaseUrl()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(roomsOverall -> { .subscribe(roomsOverall -> {

View File

@ -185,13 +185,20 @@ public class OperationsMenuController extends BaseController {
if (currentUser != null) { if (currentUser != null) {
credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()); credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken());
int apiVersion;
if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(currentUser.getBaseUrl())) { if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(currentUser.getBaseUrl())) {
credentials = null; credentials = null;
// FIXME joining a public link we need to check other capabilities
apiVersion = 1;
} else {
apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {1});
} }
switch (operationCode) { switch (operationCode) {
case 2: case 2:
ncApi.renameRoom(credentials, ApiUtils.getRoom(currentUser.getBaseUrl(), conversation.getToken()), ncApi.renameRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()),
conversation.getName()) conversation.getName())
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -199,8 +206,8 @@ public class OperationsMenuController extends BaseController {
.subscribe(operationsObserver); .subscribe(operationsObserver);
break; break;
case 3: case 3:
ncApi.makeRoomPublic(credentials, ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation ncApi.makeRoomPublic(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
.getToken())) conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(1) .retry(1)
@ -213,7 +220,7 @@ public class OperationsMenuController extends BaseController {
if (conversation.getPassword() != null) { if (conversation.getPassword() != null) {
pass = conversation.getPassword(); pass = conversation.getPassword();
} }
ncApi.setPassword(credentials, ApiUtils.getUrlForPassword(currentUser.getBaseUrl(), ncApi.setPassword(credentials, ApiUtils.getUrlForRoomPassword(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()), pass) conversation.getToken()), pass)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -224,15 +231,16 @@ public class OperationsMenuController extends BaseController {
// Operation 7 is sharing, so we handle this differently // Operation 7 is sharing, so we handle this differently
break; break;
case 8: case 8:
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion,
.getToken())) currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(1) .retry(1)
.subscribe(operationsObserver); .subscribe(operationsObserver);
break; break;
case 10: case 10:
ncApi.getRoom(credentials, ApiUtils.getRoom(baseUrl, conversationToken)) ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, baseUrl, conversationToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(1) .retry(1)
@ -271,7 +279,7 @@ public class OperationsMenuController extends BaseController {
if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) || if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) ||
!currentUser.hasSpreedFeatureCapability("empty-group-room")) { !currentUser.hasSpreedFeatureCapability("empty-group-room")) {
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(), retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
"3", invite, conversationName); "3", invite, conversationName);
} else { } else {
String roomType = "2"; String roomType = "2";
@ -280,7 +288,7 @@ public class OperationsMenuController extends BaseController {
roomType = "3"; roomType = "3";
} }
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(), retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
roomType, invite, conversationName); roomType, invite, conversationName);
} }
@ -300,7 +308,8 @@ public class OperationsMenuController extends BaseController {
conversation = roomOverall.getOcs().getData(); conversation = roomOverall.getOcs().getData();
ncApi.getRoom(credentials, ncApi.getRoom(credentials,
ApiUtils.getRoom(currentUser.getBaseUrl(), conversation.getToken())) ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<RoomOverall>() { .subscribe(new Observer<RoomOverall>() {
@ -349,14 +358,18 @@ public class OperationsMenuController extends BaseController {
case 97: case 97:
case 98: case 98:
if (operationCode == 97) { if (operationCode == 97) {
ncApi.removeConversationFromFavorites(credentials, ApiUtils.getUrlForConversationFavorites(currentUser.getBaseUrl(), ncApi.removeConversationFromFavorites(credentials,
ApiUtils.getUrlForRoomFavorite(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken())) conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(1) .retry(1)
.subscribe(operationsObserver); .subscribe(operationsObserver);
} else { } else {
ncApi.addConversationToFavorites(credentials, ApiUtils.getUrlForConversationFavorites(currentUser.getBaseUrl(), ncApi.addConversationToFavorites(credentials,
ApiUtils.getUrlForRoomFavorite(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken())) conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -365,7 +378,9 @@ public class OperationsMenuController extends BaseController {
} }
break; break;
case 99: case 99:
ncApi.joinRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, conversationToken), ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion,
baseUrl,
conversationToken),
callPassword) callPassword)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -379,7 +394,10 @@ public class OperationsMenuController extends BaseController {
} }
private void performGroupCallWorkaround(String credentials) { private void performGroupCallWorkaround(String credentials) {
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation.getToken())) int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {1});
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.retry(1) .retry(1)
@ -534,11 +552,15 @@ public class OperationsMenuController extends BaseController {
localInvitedGroups.remove(0); localInvitedGroups.remove(0);
} }
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {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"))) {
for (int i = 0; i < localInvitedGroups.size(); i++) { for (int i = 0; i < localInvitedGroups.size(); i++) {
final String groupId = localInvitedGroups.get(i); final String groupId = localInvitedGroups.get(i);
retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(currentUser.getBaseUrl(), conversation.getToken(), retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken(),
groupId); groupId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
@ -578,7 +600,9 @@ public class OperationsMenuController extends BaseController {
for (int i = 0; i < localInvitedUsers.size(); i++) { for (int i = 0; i < localInvitedUsers.size(); i++) {
final String userId = invitedUsers.get(i); final String userId = invitedUsers.get(i);
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(currentUser.getBaseUrl(), conversation.getToken(), retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken(),
userId); userId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())

View File

@ -33,8 +33,6 @@ import com.nextcloud.talk.utils.database.user.UserUtils;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -67,12 +65,16 @@ public class AddParticipantsToConversation extends Worker {
String[] selectedUserIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_USERS()); String[] selectedUserIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_USERS());
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});
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());
RetrofitBucket retrofitBucket; RetrofitBucket retrofitBucket;
for (String userId : selectedUserIds) { for (String userId : selectedUserIds) {
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(user.getBaseUrl(), conversationToken, retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(apiVersion, user.getBaseUrl(),
conversationToken,
userId); userId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
@ -81,7 +83,7 @@ public class AddParticipantsToConversation extends Worker {
} }
for (String groupId : selectedGroupIds) { for (String groupId : selectedGroupIds) {
retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(user.getBaseUrl(), conversationToken, retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(apiVersion, user.getBaseUrl(), conversationToken,
groupId); groupId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())

View File

@ -75,6 +75,8 @@ public class DeleteConversationWorker extends Worker {
UserEntity operationUser = userUtils.getUserWithId(operationUserId); UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) { if (operationUser != null) {
int apiVersion = ApiUtils.getConversationApiVersion(operationUser, new int[] {1});
String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken()); String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class); JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
@ -82,7 +84,8 @@ public class DeleteConversationWorker extends Worker {
EventStatus eventStatus = new EventStatus(operationUser.getId(), EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true); EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.deleteRoom(credentials, ApiUtils.getRoom(operationUser.getBaseUrl(), conversationToken)) ncApi.deleteRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, operationUser.getBaseUrl(),
conversationToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() { .blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable; Disposable disposable;

View File

@ -47,6 +47,7 @@ import java.net.CookieManager;
@AutoInjector(NextcloudTalkApplication.class) @AutoInjector(NextcloudTalkApplication.class)
public class LeaveConversationWorker extends Worker { public class LeaveConversationWorker extends Worker {
@Inject @Inject
Retrofit retrofit; Retrofit retrofit;
@ -82,7 +83,11 @@ public class LeaveConversationWorker extends Worker {
EventStatus eventStatus = new EventStatus(operationUser.getId(), EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true); EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForRemoveSelfFromRoom(operationUser.getBaseUrl(), conversationToken)) int apiVersion = ApiUtils.getConversationApiVersion(operationUser, new int[] {1});
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForParticipantsSelf(apiVersion,
operationUser.getBaseUrl(),
conversationToken))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() { .blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable; Disposable disposable;

View File

@ -152,8 +152,9 @@ public class NotificationWorker extends Worker {
importantConversation = Boolean.parseBoolean(arbitraryStorageEntity.getValue()); importantConversation = Boolean.parseBoolean(arbitraryStorageEntity.getValue());
} }
int apiVersion = ApiUtils.getConversationApiVersion(userEntity, new int[] {1});
ncApi.getRoom(credentials, ApiUtils.getRoom(userEntity.getBaseUrl(), ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, userEntity.getBaseUrl(),
intent.getExtras().getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) intent.getExtras().getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN())))
.blockingSubscribe(new Observer<RoomOverall>() { .blockingSubscribe(new Observer<RoomOverall>() {
@Override @Override

View File

@ -81,8 +81,11 @@ public class SignalingSettingsWorker extends Worker {
for (int i = 0; i < userEntityList.size(); i++) { for (int i = 0; i < userEntityList.size(); i++) {
userEntity = userEntityList.get(i); userEntity = userEntityList.get(i);
UserEntity finalUserEntity = userEntity; UserEntity finalUserEntity = userEntity;
int apiVersion = ApiUtils.getSignalingApiVersion(finalUserEntity, new int[] {2, 1});
ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()), ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl())) ApiUtils.getUrlForSignalingSettings(apiVersion, userEntity.getBaseUrl()))
.blockingSubscribe(new Observer<SignalingSettingsOverall>() { .blockingSubscribe(new Observer<SignalingSettingsOverall>() {
@Override @Override
public void onSubscribe(Disposable d) { public void onSubscribe(Disposable d) {

View File

@ -91,9 +91,12 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter<Mention>
queryString = ""; queryString = "";
} }
int apiVersion = ApiUtils.getChatApiVersion(currentUser, new int[] {1});
adapter.setFilter(queryString); adapter.setFilter(queryString);
ncApi.getMentionAutocompleteSuggestions(ApiUtils.getCredentials(currentUser.getUsername(), currentUser ncApi.getMentionAutocompleteSuggestions(
.getToken()), ApiUtils.getUrlForMentionSuggestions(currentUser.getBaseUrl(), roomToken), ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()),
ApiUtils.getUrlForMentionSuggestions(apiVersion, currentUser.getBaseUrl(), roomToken),
queryString, 5) queryString, 5)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())

View File

@ -21,11 +21,13 @@ package com.nextcloud.talk.utils;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.nextcloud.talk.BuildConfig; import com.nextcloud.talk.BuildConfig;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.RetrofitBucket; import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.models.database.UserEntity;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -35,21 +37,24 @@ import androidx.annotation.Nullable;
import okhttp3.Credentials; import okhttp3.Credentials;
public class ApiUtils { public class ApiUtils {
private static String ocsApiVersion = "/ocs/v2.php"; private static final String TAG = "ApiUtils";
private static String spreedApiVersion = "/apps/spreed/api/v1"; private static final String ocsApiVersion = "/ocs/v2.php";
private static final String spreedApiVersion = "/apps/spreed/api/v1";
private static final String spreedApiBase = ocsApiVersion + "/apps/spreed/api/v";
private static String userAgent = "Mozilla/5.0 (Android) Nextcloud-Talk v"; private static final String userAgent = "Mozilla/5.0 (Android) Nextcloud-Talk v";
public static String getUserAgent() { public static String getUserAgent() {
return userAgent + BuildConfig.VERSION_NAME; return userAgent + BuildConfig.VERSION_NAME;
} }
public static String getUrlForLobbyForConversation(String baseUrl, String token) { /**
return getRoom(baseUrl, token) + "/webinary/lobby"; * @deprecated This is only supported on API v1-3, in API v4+ please use
} * {@link ApiUtils#getUrlForAttendees(int, String, String)} instead.
*/
@Deprecated
public static String getUrlForRemovingParticipantFromConversation(String baseUrl, String roomToken, boolean isGuest) { public static String getUrlForRemovingParticipantFromConversation(String baseUrl, String roomToken, boolean isGuest) {
String url = getUrlForParticipants(baseUrl, roomToken); String url = getUrlForParticipants(1, baseUrl, roomToken);
if (isGuest) { if (isGuest) {
url += "/guests"; url += "/guests";
@ -100,41 +105,154 @@ public class ApiUtils {
return retrofitBucket; return retrofitBucket;
} }
public static String getUrlForSettingNotificationlevel(String baseUrl, String token) {
return getRoom(baseUrl, token) + "/notify";
}
public static String getUrlForSettingMyselfAsActiveParticipant(String baseUrl, String token) {
return getRoom(baseUrl, token) + "/participants/active";
}
public static String getUrlForParticipants(String baseUrl, String token) {
return getRoom(baseUrl, token) + "/participants";
}
public static String getUrlForCapabilities(String baseUrl) { public static String getUrlForCapabilities(String baseUrl) {
return baseUrl + ocsApiVersion + "/cloud/capabilities"; return baseUrl + ocsApiVersion + "/cloud/capabilities";
} }
public static String getUrlForGetRooms(String baseUrl) { public static int getConversationApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room"; boolean hasApiV4 = false;
for (int version : versions) {
hasApiV4 |= version == 4;
} }
public static String getRoom(String baseUrl, String token) { if (!hasApiV4) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token; Exception e = new Exception("Api call did not try conversation-v4 api");
Log.d(TAG, e.getMessage(), e);
} }
public static String getRoomV3(String baseUrl, String token) { for (int version : versions) {
return baseUrl + ocsApiVersion + "/apps/spreed/api/v3" + "/room/" + token; if (capabilities.hasSpreedFeatureCapability("conversation-v" + version)) {
return version;
} }
public static RetrofitBucket getRetrofitBucketForCreateRoom(String baseUrl, String roomType, // Fallback for old API versions
if ((version == 1 || version == 2)) {
if (capabilities.hasSpreedFeatureCapability("conversation-v2")) {
return version;
}
if (version == 1 && capabilities.hasSpreedFeatureCapability("conversation")) {
return version;
}
}
}
throw new NoSupportedApiException();
}
public static int getSignalingApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
for (int version : versions) {
if (version == 2 && capabilities.hasSpreedFeatureCapability("sip-support")) {
return version;
}
if (version == 1) {
// Has no capability, we just assume it is always there for now.
return version;
}
}
throw new NoSupportedApiException();
}
public static int getChatApiVersion(UserEntity capabilities, int[] versions) throws NoSupportedApiException {
for (int version : versions) {
if (version == 1 && capabilities.hasSpreedFeatureCapability("chat-v2")) {
// Do not question that chat-v2 capability shows the availability of api/v1/ endpoint *see no evil*
return version;
}
}
throw new NoSupportedApiException();
}
protected static String getUrlForApi(int version, String baseUrl) {
return baseUrl + spreedApiBase + version;
}
public static String getUrlForRooms(int version, String baseUrl) {
return getUrlForApi(version, baseUrl) + "/room";
}
public static String getUrlForRoom(int version, String baseUrl, String token) {
return getUrlForRooms(version, baseUrl) + "/" + token;
}
public static String getUrlForAttendees(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/attendees";
}
public static String getUrlForParticipants(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/participants";
}
public static String getUrlForParticipantsActive(int version, String baseUrl, String token) {
return getUrlForParticipants(version, baseUrl, token) + "/active";
}
public static String getUrlForParticipantsSelf(int version, String baseUrl, String token) {
return getUrlForParticipants(version, baseUrl, token) + "/self";
}
public static String getUrlForRoomFavorite(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/favorite";
}
public static String getUrlForRoomModerators(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/moderators";
}
public static String getUrlForRoomNotificationLevel(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/notify";
}
public static String getUrlForRoomPublic(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/public";
}
public static String getUrlForRoomPassword(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/password";
}
public static String getUrlForRoomReadOnlyState(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/read-only";
}
public static String getUrlForRoomWebinaryLobby(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/webinary/lobby";
}
public static String getUrlForCall(int version, String baseUrl, String token) {
return getUrlForApi(version, baseUrl) + "/call/" + token;
}
public static String getUrlForChat(int version, String baseUrl, String token) {
return getUrlForApi(version, baseUrl) + "/chat/" + token;
}
public static String getUrlForMentionSuggestions(int version, String baseUrl, String token) {
return getUrlForChat(version, baseUrl, token) + "/mentions";
}
public static String getUrlForChatMessage(int version, String baseUrl, String token, String messageId) {
return getUrlForChat(version, baseUrl, token) + "/" + messageId;
}
public static String getUrlForSignaling(int version, String baseUrl) {
return getUrlForApi(version, baseUrl) + "/signaling";
}
public static String getUrlForSignalingBackend(int version, String baseUrl) {
return getUrlForSignaling(version, baseUrl) + "/backend";
}
public static String getUrlForSignalingSettings(int version, String baseUrl) {
return getUrlForSignaling(version, baseUrl) + "/settings";
}
public static String getUrlForSignaling(int version, String baseUrl, String token) {
return getUrlForSignaling(version, baseUrl) + "/" + token;
}
public static RetrofitBucket getRetrofitBucketForCreateRoom(int version, String baseUrl, String roomType,
@Nullable String invite, @Nullable String invite,
@Nullable String conversationName) { @Nullable String conversationName) {
RetrofitBucket retrofitBucket = new RetrofitBucket(); RetrofitBucket retrofitBucket = new RetrofitBucket();
retrofitBucket.setUrl(baseUrl + ocsApiVersion + spreedApiVersion + "/room"); retrofitBucket.setUrl(getUrlForRooms(version, baseUrl));
Map<String, String> queryMap = new HashMap<>(); Map<String, String> queryMap = new HashMap<>();
queryMap.put("roomType", roomType); queryMap.put("roomType", roomType);
@ -151,9 +269,9 @@ public class ApiUtils {
return retrofitBucket; return retrofitBucket;
} }
public static RetrofitBucket getRetrofitBucketForAddParticipant(String baseUrl, String token, String user) { public static RetrofitBucket getRetrofitBucketForAddParticipant(int version, String baseUrl, String token, String user) {
RetrofitBucket retrofitBucket = new RetrofitBucket(); RetrofitBucket retrofitBucket = new RetrofitBucket();
retrofitBucket.setUrl(baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token + "/participants"); retrofitBucket.setUrl(getUrlForParticipants(version, baseUrl, token));
Map<String, String> queryMap = new HashMap<>(); Map<String, String> queryMap = new HashMap<>();
@ -165,65 +283,26 @@ public class ApiUtils {
} }
public static RetrofitBucket getRetrofitBucketForAddGroupParticipant(String baseUrl, String token, String group) { public static RetrofitBucket getRetrofitBucketForAddGroupParticipant(int version, String baseUrl, String token, String group) {
RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(baseUrl, token, group); RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(version, baseUrl, token, group);
retrofitBucket.getQueryMap().put("source", "groups"); retrofitBucket.getQueryMap().put("source", "groups");
return retrofitBucket; return retrofitBucket;
} }
public static RetrofitBucket getRetrofitBucketForAddMailParticipant(String baseUrl, String token, String mail) { public static RetrofitBucket getRetrofitBucketForAddMailParticipant(int version, String baseUrl, String token, String mail) {
RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(baseUrl, token, mail); RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(version, baseUrl, token, mail);
retrofitBucket.getQueryMap().put("source", "emails"); retrofitBucket.getQueryMap().put("source", "emails");
return retrofitBucket; return retrofitBucket;
} }
public static String getUrlForRemoveSelfFromRoom(String baseUrl, String token) { /**
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token + "/participants/self"; * @deprecated Method is only needed before Talk 4 which is from 2018 => todrop
} */
@Deprecated
public static String getUrlForRoomVisibility(String baseUrl, String token) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token + "/public";
}
public static String getUrlForCall(String baseUrl, String token) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/call/" + token;
}
public static String getUrlForCallPing(String baseUrl, String token) { public static String getUrlForCallPing(String baseUrl, String token) {
return getUrlForCall(baseUrl, token) + "/ping"; return getUrlForCall(1, baseUrl, token) + "/ping";
} }
public static String getUrlForChat(String baseUrl, String token) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/chat/" + token;
}
public static String getUrlForExternalServerAuthBackend(String baseUrl) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/signaling/backend";
}
public static String getUrlForMentionSuggestions(String baseUrl, String token) {
return getUrlForChat(baseUrl, token) + "/mentions";
}
public static String getUrlForSignaling(String baseUrl, @Nullable String token) {
String signalingUrl = baseUrl + ocsApiVersion + spreedApiVersion + "/signaling";
if (token == null) {
return signalingUrl;
} else {
return signalingUrl + "/" + token;
}
}
public static String getUrlForModerators(String baseUrl, String roomToken) {
return getRoom(baseUrl, roomToken) + "/moderators";
}
public static String getUrlForSignalingSettings(String baseUrl) {
return getUrlForSignaling(baseUrl, null) + "/settings";
}
public static String getUrlForUserProfile(String baseUrl) { public static String getUrlForUserProfile(String baseUrl) {
return baseUrl + ocsApiVersion + "/cloud/user"; return baseUrl + ocsApiVersion + "/cloud/user";
} }
@ -233,6 +312,7 @@ public class ApiUtils {
} }
public static String getUrlForUserSettings(String baseUrl) { public static String getUrlForUserSettings(String baseUrl) {
// FIXME Introduce API version
return baseUrl + ocsApiVersion + spreedApiVersion + "/settings/user"; return baseUrl + ocsApiVersion + spreedApiVersion + "/settings/user";
} }
@ -259,10 +339,6 @@ public class ApiUtils {
return baseUrl + "/index.php/avatar/guest/" + Uri.encode(name) + "/" + avatarSize; return baseUrl + "/index.php/avatar/guest/" + Uri.encode(name) + "/" + avatarSize;
} }
public static String getUrlForPassword(String baseUrl, String token) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token + "/password";
}
public static String getCredentials(String username, String token) { public static String getCredentials(String username, String token) {
if (TextUtils.isEmpty(username) && TextUtils.isEmpty(token)) { if (TextUtils.isEmpty(username) && TextUtils.isEmpty(token)) {
return null; return null;
@ -279,18 +355,10 @@ public class ApiUtils {
getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices"; getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices";
} }
public static String getUrlForConversationFavorites(String baseUrl, String roomToken) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + roomToken + "/favorite";
}
public static String getUrlForNotificationWithId(String baseUrl, String notificationId) { public static String getUrlForNotificationWithId(String baseUrl, String notificationId) {
return baseUrl + ocsApiVersion + "/apps/notifications/api/v2/notifications/" + notificationId; return baseUrl + ocsApiVersion + "/apps/notifications/api/v2/notifications/" + notificationId;
} }
public static String getUrlForReadOnlyState(String baseUrl, String roomToken) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + roomToken + "/read-only";
}
public static String getUrlForSearchByNumber(String baseUrl) { public static String getUrlForSearchByNumber(String baseUrl) {
return baseUrl + ocsApiVersion + "/cloud/users/search/by-phone"; return baseUrl + ocsApiVersion + "/cloud/users/search/by-phone";
} }
@ -303,10 +371,6 @@ public class ApiUtils {
return baseUrl + "/remote.php/dav/files/" + user + "/" + remotePath; return baseUrl + "/remote.php/dav/files/" + user + "/" + remotePath;
} }
public static String getUrlForMessageDeletion(String baseUrl, String token, String messageId) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/chat/" + token + "/" + messageId;
}
public static String getUrlForTempAvatar(String baseUrl) { public static String getUrlForTempAvatar(String baseUrl) {
return baseUrl + ocsApiVersion + "/apps/spreed/temp-user-avatar"; return baseUrl + ocsApiVersion + "/apps/spreed/temp-user-avatar";
} }

View File

@ -0,0 +1,23 @@
/*
* Nextcloud Talk application
*
* @author Joas Schilling
* Copyright (C) 2021 Joas Schilling <coding@schilljs.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.utils
class NoSupportedApiException : RuntimeException("No supported API version found")

View File

@ -53,6 +53,7 @@ public class DatabaseStorageModule implements StorageModule {
private boolean lobbyValue; private boolean lobbyValue;
private String messageNotificationLevel; private String messageNotificationLevel;
public DatabaseStorageModule(UserEntity conversationUser, String conversationToken) { public DatabaseStorageModule(UserEntity conversationUser, String conversationToken) {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
@ -92,8 +93,11 @@ public class DatabaseStorageModule implements StorageModule {
intValue = 0; intValue = 0;
} }
int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {4, 1});
ncApi.setNotificationLevel(ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken()), ncApi.setNotificationLevel(ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken()),
ApiUtils.getUrlForSettingNotificationlevel(conversationUser.getBaseUrl(), conversationToken), ApiUtils.getUrlForRoomNotificationLevel(apiVersion, conversationUser.getBaseUrl(),
conversationToken),
intValue) intValue)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(new Observer<GenericOverall>() { .subscribe(new Observer<GenericOverall>() {

View File

@ -88,12 +88,14 @@ public class WebSocketConnectionHelper {
} }
HelloOverallWebSocketMessage getAssembledHelloModel(UserEntity userEntity, String ticket) { HelloOverallWebSocketMessage getAssembledHelloModel(UserEntity userEntity, String ticket) {
int apiVersion = ApiUtils.getSignalingApiVersion(userEntity, new int[] {2, 1});
HelloOverallWebSocketMessage helloOverallWebSocketMessage = new HelloOverallWebSocketMessage(); HelloOverallWebSocketMessage helloOverallWebSocketMessage = new HelloOverallWebSocketMessage();
helloOverallWebSocketMessage.setType("hello"); helloOverallWebSocketMessage.setType("hello");
HelloWebSocketMessage helloWebSocketMessage = new HelloWebSocketMessage(); HelloWebSocketMessage helloWebSocketMessage = new HelloWebSocketMessage();
helloWebSocketMessage.setVersion("1.0"); helloWebSocketMessage.setVersion("1.0");
AuthWebSocketMessage authWebSocketMessage = new AuthWebSocketMessage(); AuthWebSocketMessage authWebSocketMessage = new AuthWebSocketMessage();
authWebSocketMessage.setUrl(ApiUtils.getUrlForExternalServerAuthBackend(userEntity.getBaseUrl())); authWebSocketMessage.setUrl(ApiUtils.getUrlForSignalingBackend(apiVersion, userEntity.getBaseUrl()));
AuthParametersWebSocketMessage authParametersWebSocketMessage = new AuthParametersWebSocketMessage(); AuthParametersWebSocketMessage authParametersWebSocketMessage = new AuthParametersWebSocketMessage();
authParametersWebSocketMessage.setTicket(ticket); authParametersWebSocketMessage.setTicket(ticket);
authParametersWebSocketMessage.setUserid(userEntity.getUserId()); authParametersWebSocketMessage.setUserid(userEntity.getUserId());