Merge pull request #1235 from nextcloud/feature/apiv4/open-public-link

[apiv4] 👤🏷️ Fix API calls for guests
This commit is contained in:
Joas Schilling 2021-05-12 16:55:23 +02:00 committed by GitHub
commit 20f228a715
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 372 additions and 316 deletions

View file

@ -1132,7 +1132,13 @@ public class CallController extends BaseController {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe(); .subscribe();
} catch (IOException exception) { } catch (IOException exception) {
Log.e(TAG, "Failed to serialize external signaling server"); Log.e(TAG, "Failed to serialize external signaling server", exception);
}
} else {
try {
conversationUser.setExternalSignalingServer(LoganSquare.serialize(externalSignalingServer));
} catch (IOException exception) {
Log.e(TAG, "Failed to serialize external signaling server", exception);
} }
} }
@ -1172,6 +1178,7 @@ public class CallController extends BaseController {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Log.e(TAG, e.getMessage(), e);
} }
@Override @Override

View file

@ -201,7 +201,6 @@ public class CallNotificationController extends BaseController {
private void proceedToCall() { private void proceedToCall() {
originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken()); originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName()); originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle)) getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
.popChangeHandler(new HorizontalChangeHandler()) .popChangeHandler(new HorizontalChangeHandler())

View file

@ -454,8 +454,17 @@ class ChatController(args: Bundle) :
R.layout.item_date_header, this R.layout.item_date_header, this
) )
var senderId = ""
if (!conversationUser?.userId.equals("?")) {
senderId = "users/" + conversationUser?.userId
} else {
senderId = currentConversation?.getActorType() + "/" + currentConversation?.getActorId()
}
Log.d(TAG, "Initialize TalkMessagesListAdapter with senderId: " + senderId)
adapter = TalkMessagesListAdapter( adapter = TalkMessagesListAdapter(
conversationUser?.userId, senderId,
messageHolders, messageHolders,
ImageLoader { imageView, url, payload -> ImageLoader { imageView, url, payload ->
val draweeController = Fresco.newDraweeControllerBuilder() val draweeController = Fresco.newDraweeControllerBuilder()
@ -1050,18 +1059,6 @@ class ChatController(args: Bundle) :
}) })
} }
private fun setSenderId() {
try {
val senderId = adapter?.javaClass?.getDeclaredField("senderId")
senderId?.isAccessible = true
senderId?.set(adapter, conversationUser?.userId)
} catch (e: NoSuchFieldException) {
Log.w(TAG, "Failed to set sender id")
} catch (e: IllegalAccessException) {
Log.w(TAG, "Failed to access and set field")
}
}
private fun submitMessage() { private fun submitMessage() {
if (messageInput != null) { if (messageInput != null) {
val editable = messageInput!!.editableText val editable = messageInput!!.editableText
@ -1351,14 +1348,6 @@ class ChatController(args: Bundle) :
chatMessage.activeUser = conversationUser chatMessage.activeUser = conversationUser
chatMessage.isLinkPreviewAllowed = isLinkPreviewAllowed chatMessage.isLinkPreviewAllowed = isLinkPreviewAllowed
// if credentials are empty, we're acting as a guest
if (TextUtils.isEmpty(credentials) && myFirstMessage != null && !TextUtils.isEmpty(myFirstMessage?.toString())) {
if (chatMessage.actorType == "guests") {
conversationUser?.userId = chatMessage.actorId
setSenderId()
}
}
val shouldScroll = val shouldScroll =
!isThereANewNotice && !shouldAddNewMessagesNotice && layoutManager?.findFirstVisibleItemPosition() == 0 || adapter != null && adapter?.itemCount == 0 !isThereANewNotice && !shouldAddNewMessagesNotice && layoutManager?.findFirstVisibleItemPosition() == 0 || adapter != null && adapter?.itemCount == 0
@ -1450,6 +1439,8 @@ class ChatController(args: Bundle) :
inflater.inflate(R.menu.menu_conversation, menu) inflater.inflate(R.menu.menu_conversation, menu)
if (conversationUser?.userId == "?") { if (conversationUser?.userId == "?") {
menu.removeItem(R.id.conversation_info) menu.removeItem(R.id.conversation_info)
conversationVoiceCallMenuItem = menu.findItem(R.id.conversation_voice_call)
conversationVideoMenuItem = menu.findItem(R.id.conversation_video_call)
} else { } else {
conversationInfoMenuItem = menu.findItem(R.id.conversation_info) conversationInfoMenuItem = menu.findItem(R.id.conversation_info)
conversationVoiceCallMenuItem = menu.findItem(R.id.conversation_voice_call) conversationVoiceCallMenuItem = menu.findItem(R.id.conversation_voice_call)

View file

@ -20,24 +20,21 @@
package com.nextcloud.talk.controllers.bottomsheet; package com.nextcloud.talk.controllers.bottomsheet;
import android.app.Activity; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bluelinelabs.conductor.RouterTransaction; import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler; import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
@ -58,6 +55,7 @@ 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;
import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.NoSupportedApiException;
import com.nextcloud.talk.utils.bundle.BundleKeys; import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils; import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder; import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
@ -81,6 +79,8 @@ import retrofit2.HttpException;
@AutoInjector(NextcloudTalkApplication.class) @AutoInjector(NextcloudTalkApplication.class)
public class OperationsMenuController extends BaseController { public class OperationsMenuController extends BaseController {
private static final String TAG = "OperationsMenuController";
@BindView(R.id.progress_bar) @BindView(R.id.progress_bar)
ProgressBar progressBar; ProgressBar progressBar;
@ -165,13 +165,7 @@ public class OperationsMenuController extends BaseController {
super.onViewBound(view); super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
processOperation();
}
private void processOperation() {
currentUser = userUtils.getCurrentUser(); currentUser = userUtils.getCurrentUser();
OperationsObserver operationsObserver = new OperationsObserver();
if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) { if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) {
conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1); conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1);
if (callUrl.contains("/index.php")) { if (callUrl.contains("/index.php")) {
@ -181,125 +175,182 @@ public class OperationsMenuController extends BaseController {
} }
} }
if (currentUser != null) { if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(currentUser.getBaseUrl())) {
credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()); if (serverCapabilities != null) {
try {
int apiVersion; useBundledCapabilitiesForGuest();
if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(currentUser.getBaseUrl())) { } catch (IOException e) {
credentials = null; // Fall back to fetching capabilities again
// FIXME joining a public link we need to check other capabilities fetchCapabilitiesForGuest();
apiVersion = 1; }
} else { } else {
apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1}); fetchCapabilitiesForGuest();
} }
} else {
processOperation();
}
}
switch (operationCode) { @SuppressLint("LongLogTag")
case 2: private void useBundledCapabilitiesForGuest() throws IOException {
ncApi.renameRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(), currentUser = new UserEntity();
conversation.getToken()), currentUser.setBaseUrl(baseUrl);
conversation.getName()) currentUser.setUserId("?");
.subscribeOn(Schedulers.io()) try {
.observeOn(AndroidSchedulers.mainThread()) currentUser.setCapabilities(LoganSquare.serialize(serverCapabilities));
.retry(1) } catch (IOException e) {
.subscribe(operationsObserver); Log.e("OperationsMenu", "Failed to serialize capabilities");
break; throw e;
case 3: }
ncApi.makeRoomPublic(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 4:
case 5:
case 6:
String pass = "";
if (conversation.getPassword() != null) {
pass = conversation.getPassword();
}
ncApi.setPassword(credentials, ApiUtils.getUrlForRoomPassword(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()), pass)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 7:
// Operation 7 is sharing, so we handle this differently
break;
case 8:
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 10:
ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, baseUrl, conversationToken))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(new Observer<RoomOverall>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override try {
public void onNext(RoomOverall roomOverall) { checkCapabilities(currentUser);
conversation = roomOverall.getOcs().getData(); processOperation();
fetchCapabilities(credentials); } catch (NoSupportedApiException e) {
} showResultImage(false, false);
Log.d(TAG, "No supported server version found", e);
}
}
@Override @SuppressLint("LongLogTag")
public void onError(Throwable e) { private void fetchCapabilitiesForGuest() {
showResultImage(false, false); ncApi.getCapabilities(null, ApiUtils.getUrlForCapabilities(baseUrl))
dispose(); .subscribeOn(Schedulers.io())
} .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<CapabilitiesOverall>() {
@Override @Override
public void onComplete() { public void onSubscribe(Disposable d) {
dispose();
}
});
break;
case 11:
RetrofitBucket retrofitBucket;
String invite = null;
if (invitedGroups.size() > 0) {
invite = invitedGroups.get(0);
} }
if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL)) { @SuppressLint("LongLogTag")
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(), @Override
"3", invite, conversationName); public void onNext(CapabilitiesOverall capabilitiesOverall) {
} else { currentUser = new UserEntity();
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(), currentUser.setBaseUrl(baseUrl);
"2", invite, conversationName); currentUser.setUserId("?");
try {
currentUser.setCapabilities(LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()));
} catch (IOException e) {
Log.e("OperationsMenu", "Failed to serialize capabilities");
}
try {
checkCapabilities(currentUser);
processOperation();
} catch (NoSupportedApiException e) {
showResultImage(false, false);
Log.d(TAG, "No supported server version found", e);
}
} }
ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap()) @SuppressLint("LongLogTag")
.subscribeOn(Schedulers.io()) @Override
.observeOn(AndroidSchedulers.mainThread()) public void onError(Throwable e) {
.retry(1) showResultImage(false, false);
.subscribe(new Observer<RoomOverall>() { Log.e(TAG, "Error fetching capabilities for guest", e);
@Override }
public void onSubscribe(Disposable d) {
} @Override
public void onComplete() {
@Override }
public void onNext(RoomOverall roomOverall) { });
conversation = roomOverall.getOcs().getData(); }
ncApi.getRoom(credentials, @SuppressLint("LongLogTag")
ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(), private void processOperation() {
conversation.getToken())) OperationsObserver operationsObserver = new OperationsObserver();
if (currentUser == null) {
showResultImage(false, true);
Log.e(TAG, "Ended up in processOperation without a valid currentUser");
return;
}
credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken());
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
switch (operationCode) {
case 2:
ncApi.renameRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()),
conversation.getName())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 3:
ncApi.makeRoomPublic(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 4:
case 5:
case 6:
String pass = "";
if (conversation.getPassword() != null) {
pass = conversation.getPassword();
}
ncApi.setPassword(credentials, ApiUtils.getUrlForRoomPassword(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()), pass)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 7:
// Operation 7 is sharing, so we handle this differently
break;
case 8:
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion,
currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
case 10:
ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, baseUrl, conversationToken))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(new Observer<RoomOverall>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(RoomOverall roomOverall) {
conversation = roomOverall.getOcs().getData();
if (conversation.isHasPassword() && conversation.isGuest()) {
eventBus.post(new BottomSheetLockEvent(true, 0,
true, false));
Bundle bundle = new Bundle();
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
try {
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
Parcels.wrap(LoganSquare.parse(currentUser.getCapabilities(),
Capabilities.class)));
} catch (IOException e) {
Log.e(TAG, "Failed to parse capabilities for guest");
showResultImage(false, false);
}
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (conversation.isGuest()) {
ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion,
baseUrl,
conversationToken), null)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<RoomOverall>() { .subscribe(new Observer<RoomOverall>() {
@ -311,7 +362,7 @@ 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();
inviteUsersToAConversation(); initiateConversation(false);
} }
@Override @Override
@ -325,57 +376,131 @@ public class OperationsMenuController extends BaseController {
} }
}); });
} else {
initiateConversation(false);
} }
}
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
showResultImage(false, false); showResultImage(false, false);
dispose(); dispose();
} }
@Override @Override
public void onComplete() { public void onComplete() {
dispose(); dispose();
} }
}); });
break;
case 11:
RetrofitBucket retrofitBucket;
String invite = null;
break; if (invitedGroups.size() > 0) {
case 97: invite = invitedGroups.get(0);
case 98: }
if (operationCode == 97) {
ncApi.removeConversationFromFavorites(credentials, if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL)) {
ApiUtils.getUrlForRoomFavorite(apiVersion, retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
currentUser.getBaseUrl(), "3", invite, conversationName);
conversation.getToken())) } else {
.subscribeOn(Schedulers.io()) retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion, currentUser.getBaseUrl(),
.observeOn(AndroidSchedulers.mainThread()) "2", invite, conversationName);
.retry(1) }
.subscribe(operationsObserver);
} else { ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
ncApi.addConversationToFavorites(credentials, .subscribeOn(Schedulers.io())
ApiUtils.getUrlForRoomFavorite(apiVersion, .observeOn(AndroidSchedulers.mainThread())
currentUser.getBaseUrl(), .retry(1)
conversation.getToken())) .subscribe(new Observer<RoomOverall>() {
.subscribeOn(Schedulers.io()) @Override
.observeOn(AndroidSchedulers.mainThread()) public void onSubscribe(Disposable d) {
.retry(1)
.subscribe(operationsObserver); }
}
break; @Override
case 99: public void onNext(RoomOverall roomOverall) {
ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion, conversation = roomOverall.getOcs().getData();
baseUrl,
conversationToken), ncApi.getRoom(credentials,
callPassword) ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<RoomOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomOverall roomOverall) {
conversation = roomOverall.getOcs().getData();
inviteUsersToAConversation();
}
@Override
public void onError(Throwable e) {
showResultImage(false, false);
dispose();
}
@Override
public void onComplete() {
}
});
}
@Override
public void onError(Throwable e) {
showResultImage(false, false);
dispose();
}
@Override
public void onComplete() {
dispose();
}
});
break;
case 97:
case 98:
if (operationCode == 97) {
ncApi.removeConversationFromFavorites(credentials,
ApiUtils.getUrlForRoomFavorite(apiVersion,
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; } else {
default: ncApi.addConversationToFavorites(credentials,
break; ApiUtils.getUrlForRoomFavorite(apiVersion,
} currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
}
break;
case 99:
ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion,
baseUrl,
conversationToken),
callPassword)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(operationsObserver);
break;
default:
break;
} }
} }
@ -436,58 +561,11 @@ public class OperationsMenuController extends BaseController {
dispose(); dispose();
} }
private void fetchCapabilities(String credentials) { private void checkCapabilities(UserEntity currentUser) throws NoSupportedApiException {
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl)) ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
.subscribeOn(Schedulers.io()) ApiUtils.getCallApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
.observeOn(AndroidSchedulers.mainThread()) ApiUtils.getChatApiVersion(currentUser, new int[] {1});
.subscribe(new Observer<CapabilitiesOverall>() { ApiUtils.getSignalingApiVersion(currentUser, new int[] {2, 1});
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(CapabilitiesOverall capabilitiesOverall) {
// Guest checking the capabilities so there is no global server EOL warning until here.
// FIXME check the serverEOL capabilities instead
if (capabilitiesOverall.getOcs().getData()
.getCapabilities().getSpreedCapability() != null &&
capabilitiesOverall.getOcs().getData()
.getCapabilities().getSpreedCapability()
.getFeatures() != null && capabilitiesOverall.getOcs().getData()
.getCapabilities().getSpreedCapability()
.getFeatures().contains("chat-v2")) {
if (conversation.isHasPassword() && conversation.isGuest()) {
eventBus.post(new BottomSheetLockEvent(true, 0,
true, false));
Bundle bundle = new Bundle();
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
Parcels.wrap(capabilitiesOverall.getOcs().getData().getCapabilities()));
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
initiateConversation(false, capabilitiesOverall.getOcs().getData()
.getCapabilities());
}
} else {
showResultImage(false, true);
}
}
@Override
public void onError(Throwable e) {
showResultImage(false, false);
}
@Override
public void onComplete() {
}
});
} }
private void inviteUsersToAConversation() { private void inviteUsersToAConversation() {
@ -535,7 +613,7 @@ public class OperationsMenuController extends BaseController {
} }
if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) { if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) {
initiateConversation(true, null); initiateConversation(true);
} }
dispose(); dispose();
} }
@ -577,95 +655,36 @@ public class OperationsMenuController extends BaseController {
} }
if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) { if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) {
initiateConversation(true, null); initiateConversation(true);
} }
dispose(); dispose();
} }
}); });
} }
} else { } else {
initiateConversation(true, null); initiateConversation(true);
} }
} }
private void initiateConversation(boolean dismissView, @Nullable Capabilities capabilities) { private void initiateConversation(boolean dismissView) {
Bundle bundle = new Bundle(); eventBus.post(new BottomSheetLockEvent(true, 0,
boolean isGuestUser = false; true, true, dismissView));
boolean hasChatCapability;
if (baseUrl != null && !baseUrl.equals(currentUser.getBaseUrl())) { Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
isGuestUser = true;
// Guest checking the capabilities so there is no global server EOL warning until here.
// FIXME check the serverEOL capabilities instead
hasChatCapability = capabilities != null && capabilities.getSpreedCapability() != null && capabilities.getSpreedCapability().getFeatures() != null && capabilities.getSpreedCapability().getFeatures().contains("chat-v2");
} else {
hasChatCapability = currentUser.hasSpreedFeatureCapability("chat-v2");
}
if (hasChatCapability) {
eventBus.post(new BottomSheetLockEvent(true, 0,
true, true, dismissView));
Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getRoomId());
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), conversation.getDisplayName());
UserEntity conversationUser;
if (isGuestUser) {
conversationUser = new UserEntity();
conversationUser.setBaseUrl(baseUrl);
conversationUser.setUserId("?");
try {
conversationUser.setCapabilities(LoganSquare.serialize(capabilities));
} catch (IOException e) {
Log.e("OperationsMenu", "Failed to serialize capabilities");
}
} else {
conversationUser = currentUser;
}
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
conversationIntent.putExtras(bundle);
if (getParentController() != null) {
ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(), conversationUser.getId(),
conversation.getToken(), bundle, true);
}
} else {
initiateCall();
}
}
private void initiateCall() {
eventBus.post(new BottomSheetLockEvent(true, 0, true, true));
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken()); bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getRoomId());
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), conversation.getDisplayName());
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser); bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
if (baseUrl != null && !baseUrl.equals(currentUser.getBaseUrl())) {
bundle.putString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), baseUrl);
}
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation)); bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
if (getActivity() != null) { conversationIntent.putExtras(bundle);
Intent callIntent = new Intent(getActivity(), MagicCallActivity.class);
callIntent.putExtras(bundle);
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
new Handler().postDelayed(() -> getParentController().getRouter().popCurrentController(), 100);
startActivity(callIntent);
if (getParentController() != null) {
ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(), currentUser.getId(),
conversation.getToken(), bundle, true);
} }
} }
private class OperationsObserver implements Observer { private class OperationsObserver implements Observer {
@ -678,11 +697,13 @@ public class OperationsMenuController extends BaseController {
@Override @Override
public void onNext(Object o) { public void onNext(Object o) {
if (operationCode != 99) { if (operationCode != 99) {
RoomOverall roomOverall = (RoomOverall) o;
conversation = roomOverall.getOcs().getData();
showResultImage(true, false); showResultImage(true, false);
} else { } else {
RoomOverall roomOverall = (RoomOverall) o; RoomOverall roomOverall = (RoomOverall) o;
conversation = roomOverall.getOcs().getData(); conversation = roomOverall.getOcs().getData();
initiateConversation(true, serverCapabilities); initiateConversation(true);
} }
} }

View file

@ -214,12 +214,16 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
return new IUser() { return new IUser() {
@Override @Override
public String getId() { public String getId() {
return actorId; return actorType + "/" + actorId;
} }
@Override @Override
public String getName() { public String getName() {
return actorDisplayName; if (!TextUtils.isEmpty(actorDisplayName)) {
return actorDisplayName;
}
return NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
} }
@Override @Override

View file

@ -61,6 +61,10 @@ public class Conversation {
public boolean hasPassword; public boolean hasPassword;
@JsonField(name = "sessionId") @JsonField(name = "sessionId")
public String sessionId; public String sessionId;
@JsonField(name = "actorId")
public String actorId;
@JsonField(name = "actorType")
public String actorType;
public String password; public String password;
@JsonField(name = "isFavorite") @JsonField(name = "isFavorite")
public boolean isFavorite; public boolean isFavorite;
@ -180,6 +184,14 @@ public class Conversation {
return this.participantType; return this.participantType;
} }
public String getActorId() {
return actorId;
}
public String getActorType() {
return actorType;
}
public boolean isHasPassword() { public boolean isHasPassword() {
return this.hasPassword; return this.hasPassword;
} }
@ -277,6 +289,14 @@ public class Conversation {
this.participantType = participantType; this.participantType = participantType;
} }
public void setActorId(String actorId) {
this.actorId = actorId;
}
public void setActorType(String actorType) {
this.actorType = actorType;
}
public void setHasPassword(boolean hasPassword) { public void setHasPassword(boolean hasPassword) {
this.hasPassword = hasPassword; this.hasPassword = hasPassword;
} }
@ -399,6 +419,12 @@ public class Conversation {
if (sessionId != null ? !sessionId.equals(that.sessionId) : that.sessionId != null) { if (sessionId != null ? !sessionId.equals(that.sessionId) : that.sessionId != null) {
return false; return false;
} }
if (actorId != null ? !actorId.equals(that.actorId) : that.actorId != null) {
return false;
}
if (actorType != null ? !actorType.equals(that.actorType) : that.actorType != null) {
return false;
}
if (password != null ? !password.equals(that.password) : that.password != null) { if (password != null ? !password.equals(that.password) : that.password != null) {
return false; return false;
} }
@ -441,6 +467,8 @@ public class Conversation {
result = 31 * result + (int) (lastPing ^ (lastPing >>> 32)); result = 31 * result + (int) (lastPing ^ (lastPing >>> 32));
result = 31 * result + (participants != null ? participants.hashCode() : 0); result = 31 * result + (participants != null ? participants.hashCode() : 0);
result = 31 * result + (participantType != null ? participantType.hashCode() : 0); result = 31 * result + (participantType != null ? participantType.hashCode() : 0);
result = 31 * result + (actorId != null ? actorId.hashCode() : 0);
result = 31 * result + (actorType != null ? actorType.hashCode() : 0);
result = 31 * result + (hasPassword ? 1 : 0); result = 31 * result + (hasPassword ? 1 : 0);
result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0); result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
result = 31 * result + (password != null ? password.hashCode() : 0); result = 31 * result + (password != null ? password.hashCode() : 0);
@ -473,6 +501,8 @@ public class Conversation {
", lastPing=" + lastPing + ", lastPing=" + lastPing +
", participants=" + participants + ", participants=" + participants +
", participantType=" + participantType + ", participantType=" + participantType +
", actorId=" + actorId +
", actorType=" + actorType +
", hasPassword=" + hasPassword + ", hasPassword=" + hasPassword +
", sessionId='" + sessionId + '\'' + ", sessionId='" + sessionId + '\'' +
", password='" + password + '\'' + ", password='" + password + '\'' +

View file

@ -152,9 +152,10 @@ public class MagicWebSocketInstance extends WebSocketListener {
public void restartWebSocket() { public void restartWebSocket() {
reconnecting = true; reconnecting = true;
Request request = new Request.Builder().url(connectionUrl).build(); Log.d(TAG, "restartWebSocket: " + connectionUrl);
okHttpClient.newWebSocket(request, this); Request request = new Request.Builder().url(connectionUrl).build();
restartCount++; okHttpClient.newWebSocket(request, this);
restartCount++;
} }
@Override @Override
@ -196,6 +197,7 @@ public class MagicWebSocketInstance extends WebSocketListener {
eventBus.post(new WebSocketCommunicationEvent("hello", helloHasHap)); eventBus.post(new WebSocketCommunicationEvent("hello", helloHasHap));
break; break;
case "error": case "error":
Log.e(TAG, "Received error: " + text);
ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class);
if (("no_such_session").equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { if (("no_such_session").equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) {
LoggingUtils.INSTANCE.writeLogEntryToFile(context, LoggingUtils.INSTANCE.writeLogEntryToFile(context,
@ -351,7 +353,7 @@ public class MagicWebSocketInstance extends WebSocketListener {
} }
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); Log.e(TAG, e.getMessage(), e);
} }
} }

View file

@ -98,7 +98,9 @@ public class WebSocketConnectionHelper {
authWebSocketMessage.setUrl(ApiUtils.getUrlForSignalingBackend(apiVersion, 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()); if (!userEntity.getUserId().equals("?")) {
authParametersWebSocketMessage.setUserid(userEntity.getUserId());
}
authWebSocketMessage.setAuthParametersWebSocketMessage(authParametersWebSocketMessage); authWebSocketMessage.setAuthParametersWebSocketMessage(authParametersWebSocketMessage);
helloWebSocketMessage.setAuthWebSocketMessage(authWebSocketMessage); helloWebSocketMessage.setAuthWebSocketMessage(authWebSocketMessage);
helloOverallWebSocketMessage.setHelloWebSocketMessage(helloWebSocketMessage); helloOverallWebSocketMessage.setHelloWebSocketMessage(helloWebSocketMessage);