mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 12:09:45 +01:00
More work on joining
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
902a1c1885
commit
b46c2362b7
@ -201,6 +201,8 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
private PulseAnimation pulseAnimation;
|
private PulseAnimation pulseAnimation;
|
||||||
private View.OnClickListener videoOnClickListener;
|
private View.OnClickListener videoOnClickListener;
|
||||||
|
|
||||||
|
private String baseUrl;
|
||||||
|
|
||||||
private static int getSystemUiVisibility() {
|
private static int getSystemUiVisibility() {
|
||||||
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
|
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||||
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
@ -236,6 +238,13 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
callSession = getIntent().getExtras().getString(BundleKeys.KEY_CALL_SESSION, "0");
|
callSession = getIntent().getExtras().getString(BundleKeys.KEY_CALL_SESSION, "0");
|
||||||
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||||
|
|
||||||
|
if (getIntent().getExtras().containsKey(BundleKeys.KEY_MODIFIED_BASE_URL)) {
|
||||||
|
credentials = null;
|
||||||
|
baseUrl = getIntent().getExtras().getString(BundleKeys.KEY_MODIFIED_BASE_URL);
|
||||||
|
} else {
|
||||||
|
baseUrl = userEntity.getBaseUrl();
|
||||||
|
}
|
||||||
|
|
||||||
callControls.setZ(100.0f);
|
callControls.setZ(100.0f);
|
||||||
basicInitialization();
|
basicInitialization();
|
||||||
|
|
||||||
@ -281,7 +290,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleFromNotification() {
|
private void handleFromNotification() {
|
||||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userEntity.getBaseUrl()))
|
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<RoomsOverall>() {
|
.subscribe(new Observer<RoomsOverall>() {
|
||||||
@ -676,8 +685,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
public void startPullingSignalingMessages() {
|
public void startPullingSignalingMessages() {
|
||||||
leavingCall = false;
|
leavingCall = false;
|
||||||
|
|
||||||
ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
|
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
||||||
ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl()))
|
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<SignalingSettingsOverall>() {
|
.subscribe(new Observer<SignalingSettingsOverall>() {
|
||||||
@ -737,7 +745,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void joinRoomAndCall() {
|
private void joinRoomAndCall() {
|
||||||
if (callSession.equals("0")) {
|
if (callSession.equals("0")) {
|
||||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), roomToken), null)
|
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken), null)
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
@ -769,7 +777,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void performCall(@Nullable String callSessionId) {
|
private void performCall(@Nullable String callSessionId) {
|
||||||
ncApi.joinCall(credentials,
|
ncApi.joinCall(credentials,
|
||||||
ApiUtils.getUrlForCall(userEntity.getBaseUrl(), roomToken))
|
ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -787,8 +795,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start pinging the call
|
// start pinging the call
|
||||||
ncApi.pingCall(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
|
ncApi.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
||||||
ApiUtils.getUrlForCallPing(userEntity.getBaseUrl(), roomToken))
|
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.repeatWhen(observable -> observable.delay(5000, TimeUnit.MILLISECONDS))
|
.repeatWhen(observable -> observable.delay(5000, TimeUnit.MILLISECONDS))
|
||||||
@ -817,8 +824,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Start pulling signaling messages
|
// Start pulling signaling messages
|
||||||
ncApi.pullSignalingMessages(ApiUtils.getCredentials(userEntity.getUsername(),
|
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl))
|
||||||
userEntity.getToken()), ApiUtils.getUrlForSignaling(userEntity.getBaseUrl()))
|
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.repeatWhen(observable -> observable)
|
.repeatWhen(observable -> observable)
|
||||||
@ -945,8 +951,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
Set<String> oldSesssions = new HashSet<>();
|
Set<String> oldSesssions = new HashSet<>();
|
||||||
|
|
||||||
for (HashMap<String, String> participant : users) {
|
for (HashMap<String, String> participant : users) {
|
||||||
if (!participant.get("sessionId").equals(callSession) && !participant.get("userId").equals(userEntity
|
if (!participant.get("sessionId").equals(callSession)) {
|
||||||
.getUserId())) {
|
|
||||||
Object inCallObject = participant.get("inCall");
|
Object inCallObject = participant.get("inCall");
|
||||||
if ((boolean) inCallObject) {
|
if ((boolean) inCallObject) {
|
||||||
newSessions.add(participant.get("sessionId"));
|
newSessions.add(participant.get("sessionId"));
|
||||||
@ -1050,7 +1055,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
localAudioTrack = null;
|
localAudioTrack = null;
|
||||||
localVideoTrack = null;
|
localVideoTrack = null;
|
||||||
|
|
||||||
if (!dueToNetworkChange) {
|
if (!dueToNetworkChange && credentials != null) {
|
||||||
hangupNetworkCalls();
|
hangupNetworkCalls();
|
||||||
} else {
|
} else {
|
||||||
finish();
|
finish();
|
||||||
@ -1058,8 +1063,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hangupNetworkCalls() {
|
private void hangupNetworkCalls() {
|
||||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||||
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(userEntity.getBaseUrl(), roomToken))
|
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<GenericOverall>() {
|
.subscribe(new Observer<GenericOverall>() {
|
||||||
@ -1070,7 +1074,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(GenericOverall genericOverall) {
|
public void onNext(GenericOverall genericOverall) {
|
||||||
ncApi.leaveRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), roomToken))
|
ncApi.leaveRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken))
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<GenericOverall>() {
|
.subscribe(new Observer<GenericOverall>() {
|
||||||
@ -1277,7 +1281,6 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||||
public void onMessageEvent(SessionDescriptionSendEvent sessionDescriptionSend) throws IOException {
|
public void onMessageEvent(SessionDescriptionSendEvent sessionDescriptionSend) throws IOException {
|
||||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
|
||||||
NCMessageWrapper ncMessageWrapper = new NCMessageWrapper();
|
NCMessageWrapper ncMessageWrapper = new NCMessageWrapper();
|
||||||
ncMessageWrapper.setEv("message");
|
ncMessageWrapper.setEv("message");
|
||||||
ncMessageWrapper.setSessionId(callSession);
|
ncMessageWrapper.setSessionId(callSession);
|
||||||
@ -1317,7 +1320,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
String stringToSend = stringBuilder.toString();
|
String stringToSend = stringBuilder.toString();
|
||||||
strings.add(stringToSend);
|
strings.add(stringToSend);
|
||||||
|
|
||||||
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(userEntity.getBaseUrl()),
|
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl),
|
||||||
strings.toString())
|
strings.toString())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
@ -1427,7 +1430,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
hangup(false);
|
onHangupClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class microphoneButtonTouchListener implements View.OnTouchListener {
|
private class microphoneButtonTouchListener implements View.OnTouchListener {
|
||||||
|
@ -143,34 +143,34 @@ public interface NcApi {
|
|||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<CallOverall> joinRoom(@Header("Authorization") String authorization, @Url String url,
|
Observable<CallOverall> joinRoom(@Nullable @Header("Authorization") String authorization, @Url String url,
|
||||||
@Nullable @Field("password") String password);
|
@Nullable @Field("password") String password);
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
Observable<GenericOverall> leaveRoom(@Header("Authorization") String authorization, @Url String url);
|
Observable<GenericOverall> leaveRoom(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> joinCall(@Header("Authorization") String authorization, @Url String url);
|
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
Observable<GenericOverall> leaveCall(@Header("Authorization") String authorization, @Url String url);
|
Observable<GenericOverall> leaveCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken/ping
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken/ping
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> pingCall(@Header("Authorization") String authorization, @Url String url);
|
Observable<GenericOverall> pingCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
Observable<SignalingSettingsOverall> getSignalingSettings(@Header("Authorization") String authorization, @Url
|
Observable<SignalingSettingsOverall> getSignalingSettings(@Nullable @Header("Authorization") String authorization,
|
||||||
String url);
|
@Url String url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
QueryMap items are as follows:
|
QueryMap items are as follows:
|
||||||
@ -180,14 +180,16 @@ public interface NcApi {
|
|||||||
*/
|
*/
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<SignalingOverall> sendSignalingMessages(@Header("Authorization") String authorization, @Url String url,
|
Observable<SignalingOverall> sendSignalingMessages(@Nullable@Header("Authorization") String authorization, @Url String url,
|
||||||
@Field("messages") String messages);
|
@Field("messages") String messages);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
Observable<SignalingOverall> pullSignalingMessages(@Header("Authorization") String authorization, @Url String url);
|
Observable<SignalingOverall> pullSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url
|
||||||
|
String
|
||||||
|
url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
QueryMap items are as follows:
|
QueryMap items are as follows:
|
||||||
|
@ -113,6 +113,31 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Pro
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
ProviderInstaller.installIfNeededAsync(this, this);
|
ProviderInstaller.installIfNeededAsync(this, this);
|
||||||
|
|
||||||
|
/*if (Build.MANUFACTURER.equalsIgnoreCase("huawei")) {
|
||||||
|
try {
|
||||||
|
Class<?> enclosingClass = Class.forName("com.huawei.systemmanager.startupmgr.db.StartupDataMgrHelper");
|
||||||
|
Method method = enclosingClass.getMethod("modifyNormalStartupInfoStatus", Context.class, String.class, boolean.class);
|
||||||
|
method.invoke(null, getApplicationContext(), getPackageName(), true);
|
||||||
|
|
||||||
|
Class<?> secondaryEnclosingClass = Class.forName("com.huawei.systemmanager.optimize.process" +
|
||||||
|
".ProtectAppControl");
|
||||||
|
Method secondaryMethod = secondaryEnclosingClass.getMethod("getInstance", Context.class);
|
||||||
|
Object object = secondaryMethod.invoke(null, getApplicationContext());
|
||||||
|
Method thirdMethod = secondaryEnclosingClass.getMethod("setNoProtect", List.class);
|
||||||
|
List<String> packageNames = new ArrayList<>();
|
||||||
|
packageNames.add(getPackageName());
|
||||||
|
thirdMethod.invoke(object, packageNames);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
Log.e(TAG, "Failed to find the required class on Huawei");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
Log.e(TAG, "Failed to find the appropriate method");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Log.e(TAG, "Illegal access exception");
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
Log.e(TAG, "Invocation target exception");
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
JobManager.create(this).addJobCreator(new MagicJobCreator());
|
JobManager.create(this).addJobCreator(new MagicJobCreator());
|
||||||
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(false);
|
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(false);
|
||||||
|
|
||||||
@ -138,6 +163,8 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void prepareThingsForStrangePhones() {
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onTerminate() {
|
public void onTerminate() {
|
||||||
super.onTerminate();
|
super.onTerminate();
|
||||||
|
@ -231,16 +231,9 @@ public class CallsListController extends BaseController implements SearchView.On
|
|||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_new_conversation:
|
case R.id.action_new_conversation:
|
||||||
searchItem.setVisible(false);
|
|
||||||
menuVariable.findItem(R.id.action_new_conversation).setVisible(false);
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true);
|
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(CallMenuController.MenuType.NEW_CONVERSATION));
|
||||||
if (getParentController() != null) {
|
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||||
getParentController().getRouter().pushController(
|
|
||||||
(RouterTransaction.with(new ContactsController(bundle))
|
|
||||||
.pushChangeHandler(new VerticalChangeHandler())
|
|
||||||
.popChangeHandler(new VerticalChangeHandler())));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
@ -445,6 +438,7 @@ public class CallsListController extends BaseController implements SearchView.On
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
Room room = moreMenuClickEvent.getRoom();
|
Room room = moreMenuClickEvent.getRoom();
|
||||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(CallMenuController.MenuType.REGULAR));
|
||||||
|
|
||||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||||
}
|
}
|
||||||
@ -455,13 +449,13 @@ public class CallsListController extends BaseController implements SearchView.On
|
|||||||
if (shouldShowCallMenuController) {
|
if (shouldShowCallMenuController) {
|
||||||
getChildRouter((ViewGroup) view).setRoot(
|
getChildRouter((ViewGroup) view).setRoot(
|
||||||
RouterTransaction.with(new CallMenuController(bundle))
|
RouterTransaction.with(new CallMenuController(bundle))
|
||||||
.popChangeHandler(new HorizontalChangeHandler())
|
.popChangeHandler(new VerticalChangeHandler())
|
||||||
.pushChangeHandler(new HorizontalChangeHandler()));
|
.pushChangeHandler(new VerticalChangeHandler()));
|
||||||
} else {
|
} else {
|
||||||
getChildRouter((ViewGroup) view).setRoot(
|
getChildRouter((ViewGroup) view).setRoot(
|
||||||
RouterTransaction.with(new EntryMenuController(bundle))
|
RouterTransaction.with(new EntryMenuController(bundle))
|
||||||
.popChangeHandler(new HorizontalChangeHandler())
|
.popChangeHandler(new VerticalChangeHandler())
|
||||||
.pushChangeHandler(new HorizontalChangeHandler()));
|
.pushChangeHandler(new VerticalChangeHandler()));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isNew = false;
|
boolean isNew = false;
|
||||||
|
@ -32,11 +32,14 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction;
|
import com.bluelinelabs.conductor.RouterTransaction;
|
||||||
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||||
|
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
|
||||||
import com.kennyc.bottomsheet.adapters.AppAdapter;
|
import com.kennyc.bottomsheet.adapters.AppAdapter;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.adapters.items.AppItem;
|
import com.nextcloud.talk.adapters.items.AppItem;
|
||||||
import com.nextcloud.talk.adapters.items.MenuItem;
|
import com.nextcloud.talk.adapters.items.MenuItem;
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
|
import com.nextcloud.talk.controllers.ContactsController;
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
import com.nextcloud.talk.controllers.base.BaseController;
|
||||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||||
import com.nextcloud.talk.models.json.rooms.Room;
|
import com.nextcloud.talk.models.json.rooms.Room;
|
||||||
@ -45,6 +48,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.parceler.Parcel;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -73,14 +77,19 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
private List<AbstractFlexibleItem> menuItems;
|
private List<AbstractFlexibleItem> menuItems;
|
||||||
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
||||||
|
|
||||||
private boolean isShare;
|
@Parcel
|
||||||
|
public enum MenuType {
|
||||||
|
REGULAR, SHARE, NEW_CONVERSATION
|
||||||
|
}
|
||||||
|
|
||||||
|
private MenuType menuType;
|
||||||
private Intent shareIntent;
|
private Intent shareIntent;
|
||||||
|
|
||||||
public CallMenuController(Bundle args) {
|
public CallMenuController(Bundle args) {
|
||||||
super(args);
|
super(args);
|
||||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||||
if (args.containsKey(BundleKeys.KEY_IS_SHARE)) {
|
if (args.containsKey(BundleKeys.KEY_MENU_TYPE)) {
|
||||||
this.isShare = true;
|
this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_MENU_TYPE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +133,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
private void prepareMenu() {
|
private void prepareMenu() {
|
||||||
menuItems = new ArrayList<>();
|
menuItems = new ArrayList<>();
|
||||||
|
|
||||||
if (!isShare) {
|
if (menuType.equals(MenuType.REGULAR)) {
|
||||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
|
||||||
|
|
||||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
|
||||||
@ -156,7 +165,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
if (room.isDeletable()) {
|
if (room.isDeletable()) {
|
||||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (menuType.equals(MenuType.SHARE)) {
|
||||||
prepareIntent();
|
prepareIntent();
|
||||||
List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
|
List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
|
||||||
null);
|
null);
|
||||||
@ -167,6 +176,10 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
|
menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
|
||||||
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_new_conversation), 1));
|
||||||
|
menuItems.add(new MenuItem(getResources().getString(R.string.nc_join_via_link), 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +188,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||||
|
|
||||||
if (!isShare) {
|
if (menuType.equals(MenuType.REGULAR)) {
|
||||||
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
||||||
if (menuItem != null) {
|
if (menuItem != null) {
|
||||||
|
|
||||||
@ -188,16 +201,22 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
|
||||||
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
|
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(new HorizontalChangeHandler()));
|
||||||
} else if (tag != 7) {
|
} else if (tag != 7) {
|
||||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||||
|
.pushChangeHandler(new VerticalChangeHandler())
|
||||||
|
.popChangeHandler(new VerticalChangeHandler()));
|
||||||
} else {
|
} else {
|
||||||
bundle.putBoolean(BundleKeys.KEY_IS_SHARE, true);
|
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(MenuType.SHARE));
|
||||||
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle))
|
||||||
|
.pushChangeHandler(new VerticalChangeHandler())
|
||||||
|
.popChangeHandler(new VerticalChangeHandler()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (position != 0) {
|
} else if (menuType.equals(MenuType.SHARE) && position != 0) {
|
||||||
AppItem appItem = (AppItem) adapter.getItem(position);
|
AppItem appItem = (AppItem) adapter.getItem(position);
|
||||||
if (appItem != null && getActivity() != null) {
|
if (appItem != null && getActivity() != null) {
|
||||||
if (!room.hasPassword) {
|
if (!room.hasPassword) {
|
||||||
@ -213,7 +232,30 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
|||||||
bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
|
bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
|
||||||
bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
|
bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
|
||||||
bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
|
bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
|
||||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||||
|
.pushChangeHandler(new VerticalChangeHandler())
|
||||||
|
.popChangeHandler(new VerticalChangeHandler()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (menuType.equals(MenuType.NEW_CONVERSATION) && position != 0) {
|
||||||
|
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
||||||
|
if (menuItem != null) {
|
||||||
|
if (menuItem.getTag() == 1) {
|
||||||
|
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||||
|
bundle = new Bundle();
|
||||||
|
bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true);
|
||||||
|
if (getParentController() != null && getParentController().getParentController() != null) {
|
||||||
|
getParentController().getParentController().getRouter().pushController(
|
||||||
|
(RouterTransaction.with(new ContactsController(bundle))
|
||||||
|
.pushChangeHandler(new VerticalChangeHandler())
|
||||||
|
.popChangeHandler(new VerticalChangeHandler())));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bundle = new Bundle();
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 10);
|
||||||
|
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||||
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(new HorizontalChangeHandler()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction;
|
import com.bluelinelabs.conductor.RouterTransaction;
|
||||||
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||||
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.controllers.base.BaseController;
|
import com.nextcloud.talk.controllers.base.BaseController;
|
||||||
@ -84,7 +85,9 @@ public class EntryMenuController extends BaseController {
|
|||||||
public EntryMenuController(Bundle args) {
|
public EntryMenuController(Bundle args) {
|
||||||
super(args);
|
super(args);
|
||||||
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
||||||
|
if (args.containsKey(BundleKeys.KEY_ROOM)) {
|
||||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||||
|
}
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
|
if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
|
||||||
this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
|
this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
|
||||||
@ -123,12 +126,13 @@ public class EntryMenuController extends BaseController {
|
|||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||||
bundle = new Bundle();
|
bundle = new Bundle();
|
||||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
|
||||||
bundle.putString(BundleKeys.KEY_CALL_PASSWORD, editText.getText().toString());
|
bundle.putString(BundleKeys.KEY_CALL_PASSWORD, editText.getText().toString());
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(new HorizontalChangeHandler()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (operationCode != 7) {
|
} else if (operationCode != 7 && operationCode != 10) {
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||||
bundle = new Bundle();
|
bundle = new Bundle();
|
||||||
if (operationCode == 4 || operationCode == 6) {
|
if (operationCode == 4 || operationCode == 6) {
|
||||||
@ -138,8 +142,10 @@ public class EntryMenuController extends BaseController {
|
|||||||
}
|
}
|
||||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||||
} else {
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(new HorizontalChangeHandler()));
|
||||||
|
} else if (operationCode == 7) {
|
||||||
if (getActivity() != null) {
|
if (getActivity() != null) {
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
|
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
|
||||||
editText.getText().toString(), userUtils, room));
|
editText.getText().toString(), userUtils, room));
|
||||||
@ -149,6 +155,15 @@ public class EntryMenuController extends BaseController {
|
|||||||
getActivity().startActivity(intent);
|
getActivity().startActivity(intent);
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||||
|
bundle = new Bundle();
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
|
||||||
|
bundle.putString(BundleKeys.KEY_CALL_URL, editText.getText().toString());
|
||||||
|
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(new HorizontalChangeHandler()));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,11 +208,27 @@ public class EntryMenuController extends BaseController {
|
|||||||
textFieldBoxes.setError(getResources().getString(R.string.nc_call_name_is_same),
|
textFieldBoxes.setError(getResources().getString(R.string.nc_call_name_is_same),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (operationCode != 10) {
|
||||||
if (!proceedButton.isEnabled()) {
|
if (!proceedButton.isEnabled()) {
|
||||||
proceedButton.setEnabled(true);
|
proceedButton.setEnabled(true);
|
||||||
proceedButton.setAlpha(1.0f);
|
proceedButton.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
|
} else if (editText.getText().toString().startsWith("http://") ||
|
||||||
|
editText.getText().toString().startsWith("https://") &&
|
||||||
|
editText.getText().toString().contains("/call/")) {
|
||||||
|
// operation code 10
|
||||||
|
if (!proceedButton.isEnabled()) {
|
||||||
|
proceedButton.setEnabled(true);
|
||||||
|
proceedButton.setAlpha(1.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (proceedButton.isEnabled()) {
|
||||||
|
proceedButton.setEnabled(false);
|
||||||
|
proceedButton.setAlpha(0.7f);
|
||||||
|
}
|
||||||
|
textFieldBoxes.setError(getResources().getString(R.string.nc_wrong_link),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (proceedButton.isEnabled()) {
|
if (proceedButton.isEnabled()) {
|
||||||
@ -219,8 +250,12 @@ public class EntryMenuController extends BaseController {
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 99:
|
case 99:
|
||||||
|
// 99 is joining a room via password
|
||||||
labelText = getResources().getString(R.string.nc_password);
|
labelText = getResources().getString(R.string.nc_password);
|
||||||
break;
|
break;
|
||||||
|
case 10:
|
||||||
|
labelText = getResources().getString(R.string.nc_conversation_link);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
import com.nextcloud.talk.controllers.base.BaseController;
|
||||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
import com.nextcloud.talk.models.database.UserEntity;
|
||||||
import com.nextcloud.talk.models.json.call.CallOverall;
|
|
||||||
import com.nextcloud.talk.models.json.rooms.Room;
|
import com.nextcloud.talk.models.json.rooms.Room;
|
||||||
|
import com.nextcloud.talk.models.json.rooms.RoomOverall;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
import com.nextcloud.talk.utils.ApiUtils;
|
||||||
import com.nextcloud.talk.utils.ApplicationWideMessageHolder;
|
import com.nextcloud.talk.utils.ApplicationWideMessageHolder;
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
import com.nextcloud.talk.utils.DisplayUtils;
|
||||||
@ -90,21 +90,21 @@ public class OperationsMenuController extends BaseController {
|
|||||||
|
|
||||||
private UserEntity userEntity;
|
private UserEntity userEntity;
|
||||||
private String callPassword;
|
private String callPassword;
|
||||||
|
private String callUrl;
|
||||||
|
|
||||||
|
private String baseUrl;
|
||||||
|
|
||||||
private Disposable disposable;
|
private Disposable disposable;
|
||||||
private Disposable secondaryDisposable;
|
|
||||||
|
|
||||||
private int retryCount = 0;
|
|
||||||
|
|
||||||
public OperationsMenuController(Bundle args) {
|
public OperationsMenuController(Bundle args) {
|
||||||
super(args);
|
super(args);
|
||||||
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
||||||
|
if (args.containsKey(BundleKeys.KEY_ROOM)) {
|
||||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||||
|
}
|
||||||
|
|
||||||
this.callPassword = args.getString(BundleKeys.KEY_CALL_PASSWORD, "");
|
this.callPassword = args.getString(BundleKeys.KEY_CALL_PASSWORD, "");
|
||||||
if (args.containsKey(BundleKeys.KEY_USER_ENTITY)) {
|
this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "");
|
||||||
this.userEntity = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_USER_ENTITY));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,7 +121,7 @@ public class OperationsMenuController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processOperation() {
|
private void processOperation() {
|
||||||
UserEntity userEntity = userUtils.getCurrentUser();
|
userEntity = userUtils.getCurrentUser();
|
||||||
OperationsObserver operationsObserver = new OperationsObserver();
|
OperationsObserver operationsObserver = new OperationsObserver();
|
||||||
if (userEntity != null) {
|
if (userEntity != null) {
|
||||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||||
@ -181,6 +181,46 @@ public class OperationsMenuController extends BaseController {
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.retry(1)
|
.retry(1)
|
||||||
.subscribe(operationsObserver);
|
.subscribe(operationsObserver);
|
||||||
|
case 10:
|
||||||
|
String conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1, callUrl.length());
|
||||||
|
if (callUrl.contains("/index.php")) {
|
||||||
|
baseUrl = callUrl.substring(0, callUrl.indexOf("/index.php"));
|
||||||
|
} else {
|
||||||
|
baseUrl = callUrl.substring(0, callUrl.indexOf("/call"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ncApi.getRoom(credentials, ApiUtils.getRoom(baseUrl, conversationToken))
|
||||||
|
.subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(new Observer<RoomOverall>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(Disposable d) {
|
||||||
|
disposable = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(RoomOverall roomOverall) {
|
||||||
|
room = roomOverall.getOcs().getData();
|
||||||
|
if (room.isHasPassword() && room.isGuest()) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
initiateCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
showResultImage(false, false);
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
case 99:
|
case 99:
|
||||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), room.getToken()),
|
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), room.getToken()),
|
||||||
callPassword)
|
callPassword)
|
||||||
@ -195,7 +235,7 @@ public class OperationsMenuController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showResultImage(boolean everythingOK) {
|
private void showResultImage(boolean everythingOK, boolean isSignalingSettingsError) {
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
if (everythingOK) {
|
if (everythingOK) {
|
||||||
@ -212,7 +252,11 @@ public class OperationsMenuController extends BaseController {
|
|||||||
resultsTextView.setText(R.string.nc_all_ok_operation);
|
resultsTextView.setText(R.string.nc_all_ok_operation);
|
||||||
} else {
|
} else {
|
||||||
resultsTextView.setTextColor(getResources().getColor(R.color.nc_darkRed));
|
resultsTextView.setTextColor(getResources().getColor(R.color.nc_darkRed));
|
||||||
|
if (!isSignalingSettingsError) {
|
||||||
resultsTextView.setText(R.string.nc_failed_to_perform_operation);
|
resultsTextView.setText(R.string.nc_failed_to_perform_operation);
|
||||||
|
} else {
|
||||||
|
resultsTextView.setText(R.string.nc_failed_signaling_settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultsTextView.setVisibility(View.VISIBLE);
|
resultsTextView.setVisibility(View.VISIBLE);
|
||||||
@ -221,8 +265,8 @@ public class OperationsMenuController extends BaseController {
|
|||||||
} else {
|
} else {
|
||||||
resultImageView.setImageDrawable(DisplayUtils.getTintedDrawable(getResources(), R.drawable
|
resultImageView.setImageDrawable(DisplayUtils.getTintedDrawable(getResources(), R.drawable
|
||||||
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
||||||
okButton.setOnClickListener(v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99,
|
okButton.setOnClickListener(v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99
|
||||||
true)));
|
&& operationCode != 10, true)));
|
||||||
okButton.setVisibility(View.VISIBLE);
|
okButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,35 +285,41 @@ public class OperationsMenuController extends BaseController {
|
|||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OperationsObserver implements Observer {
|
private void initiateCall() {
|
||||||
|
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
disposable = d;
|
|
||||||
retryCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(Object o) {
|
|
||||||
if (operationCode != 99) {
|
|
||||||
showResultImage(true);
|
|
||||||
} else {
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
|
||||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
||||||
bundle.putString(BundleKeys.KEY_CALL_SESSION, ((CallOverall) o).getOcs().getData().getSessionId());
|
if (!baseUrl.equals(userEntity.getBaseUrl())) {
|
||||||
|
bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, baseUrl);
|
||||||
|
}
|
||||||
overridePushHandler(new NoOpControllerChangeHandler());
|
overridePushHandler(new NoOpControllerChangeHandler());
|
||||||
overridePopHandler(new NoOpControllerChangeHandler());
|
overridePopHandler(new NoOpControllerChangeHandler());
|
||||||
Intent callIntent = new Intent(getActivity(), CallActivity.class);
|
Intent callIntent = new Intent(getActivity(), CallActivity.class);
|
||||||
callIntent.putExtras(bundle);
|
callIntent.putExtras(bundle);
|
||||||
startActivity(callIntent);
|
startActivity(callIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class OperationsObserver implements Observer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(Disposable d) {
|
||||||
|
disposable = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(Object o) {
|
||||||
|
if (operationCode != 99) {
|
||||||
|
showResultImage(true, false);
|
||||||
|
} else {
|
||||||
|
initiateCall();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable e) {
|
public void onError(Throwable e) {
|
||||||
if (operationCode != 99 || !(e instanceof HttpException)) {
|
if (operationCode != 99 || !(e instanceof HttpException)) {
|
||||||
showResultImage(false);
|
showResultImage(false, false);
|
||||||
} else {
|
} else {
|
||||||
if (((HttpException) e).response().code() == 403) {
|
if (((HttpException) e).response().code() == 403) {
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, false,
|
eventBus.post(new BottomSheetLockEvent(true, 0, false,
|
||||||
@ -277,7 +327,7 @@ public class OperationsMenuController extends BaseController {
|
|||||||
ApplicationWideMessageHolder.getInstance().setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG);
|
ApplicationWideMessageHolder.getInstance().setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG);
|
||||||
getRouter().popCurrentController();
|
getRouter().popCurrentController();
|
||||||
} else {
|
} else {
|
||||||
showResultImage(false);
|
showResultImage(false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispose();
|
dispose();
|
||||||
|
222
app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
Normal file
222
app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.jobs;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.bluelinelabs.logansquare.LoganSquare;
|
||||||
|
import com.evernote.android.job.Job;
|
||||||
|
import com.evernote.android.job.util.support.PersistableBundleCompat;
|
||||||
|
import com.nextcloud.talk.R;
|
||||||
|
import com.nextcloud.talk.activities.CallActivity;
|
||||||
|
import com.nextcloud.talk.models.SignatureVerification;
|
||||||
|
import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
|
||||||
|
import com.nextcloud.talk.models.json.push.PushMessage;
|
||||||
|
import com.nextcloud.talk.utils.NotificationUtils;
|
||||||
|
import com.nextcloud.talk.utils.PushUtils;
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||||
|
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
|
||||||
|
public class NotificationJob extends Job {
|
||||||
|
public static final String TAG = "NotificationJob";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected Result onRunJob(Params params) {
|
||||||
|
Context context = getContext();
|
||||||
|
PersistableBundleCompat persistableBundleCompat = getParams().getExtras();
|
||||||
|
String subject = persistableBundleCompat.getString(BundleKeys.KEY_NOTIFICATION_SUBJECT, "");
|
||||||
|
String signature = persistableBundleCompat.getString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, "");
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(subject) && !TextUtils.isEmpty(signature)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
PushMessage pushMessage = new PushMessage();
|
||||||
|
pushMessage.setSubject(subject);
|
||||||
|
pushMessage.setSignature(signature);
|
||||||
|
|
||||||
|
byte[] base64DecodedSubject = Base64.decode(pushMessage.getSubject(), Base64.DEFAULT);
|
||||||
|
byte[] base64DecodedSignature = Base64.decode(pushMessage.getSignature(), Base64.DEFAULT);
|
||||||
|
PushUtils pushUtils = new PushUtils();
|
||||||
|
PrivateKey privateKey = (PrivateKey) pushUtils.readKeyFromFile(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
SignatureVerification signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
|
||||||
|
base64DecodedSubject);
|
||||||
|
|
||||||
|
if (signatureVerification.isSignatureValid()) {
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] decryptedSubject = cipher.doFinal(base64DecodedSubject);
|
||||||
|
DecryptedPushMessage decryptedPushMessage = LoganSquare.parse(new String(decryptedSubject),
|
||||||
|
DecryptedPushMessage.class);
|
||||||
|
|
||||||
|
if (decryptedPushMessage.getApp().equals("spreed")) {
|
||||||
|
int smallIcon;
|
||||||
|
Bitmap largeIcon;
|
||||||
|
String category = "";
|
||||||
|
int priority = Notification.PRIORITY_DEFAULT;
|
||||||
|
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, CallActivity.class);
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(signatureVerification
|
||||||
|
.getUserEntity()));
|
||||||
|
bundle.putBoolean("fromNotification", true);
|
||||||
|
intent.putExtras(bundle);
|
||||||
|
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(context,
|
||||||
|
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
|
NotificationManager notificationManager =
|
||||||
|
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
switch (decryptedPushMessage.getType()) {
|
||||||
|
case "call":
|
||||||
|
smallIcon = R.drawable.ic_call_black_24dp;
|
||||||
|
category = Notification.CATEGORY_CALL;
|
||||||
|
priority = Notification.PRIORITY_HIGH;
|
||||||
|
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||||
|
break;
|
||||||
|
case "room":
|
||||||
|
smallIcon = R.drawable.ic_notifications_black_24dp;
|
||||||
|
category = Notification.CATEGORY_CALL;
|
||||||
|
priority = Notification.PRIORITY_HIGH;
|
||||||
|
break;
|
||||||
|
case "chat":
|
||||||
|
smallIcon = R.drawable.ic_chat_black_24dp;
|
||||||
|
category = Notification.CATEGORY_MESSAGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
smallIcon = R.drawable.ic_logo;
|
||||||
|
}
|
||||||
|
|
||||||
|
largeIcon = BitmapFactory.decodeResource(context.getResources(), smallIcon);
|
||||||
|
CRC32 crc32 = new CRC32();
|
||||||
|
|
||||||
|
Notification.Builder notificationBuilder = new Notification.Builder(context)
|
||||||
|
.setLargeIcon(largeIcon)
|
||||||
|
.setSmallIcon(smallIcon)
|
||||||
|
.setCategory(category)
|
||||||
|
.setPriority(priority)
|
||||||
|
.setWhen(Calendar.getInstance().getTimeInMillis())
|
||||||
|
.setShowWhen(true)
|
||||||
|
.setSubText(signatureVerification.getUserEntity().getDisplayName())
|
||||||
|
.setContentTitle(decryptedPushMessage.getSubject())
|
||||||
|
.setSound(soundUri)
|
||||||
|
.setAutoCancel(true);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
// This method should exist since API 21, but some phones don't have it
|
||||||
|
// So as a safeguard, we don't use it until 23
|
||||||
|
notificationBuilder.setColor(context.getResources().getColor(R.color.colorPrimary));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
|
||||||
|
String groupName = String.format(context.getResources().getString(R.string
|
||||||
|
.nc_notification_channel), signatureVerification.getUserEntity()
|
||||||
|
.getDisplayName(), signatureVerification.getUserEntity().getBaseUrl());
|
||||||
|
crc32.update(groupName.getBytes());
|
||||||
|
|
||||||
|
NotificationUtils.createNotificationChannelGroup(notificationManager,
|
||||||
|
Long.toString(crc32.getValue()),
|
||||||
|
groupName);
|
||||||
|
|
||||||
|
if (category.equals(Notification.CATEGORY_CALL)) {
|
||||||
|
NotificationUtils.createNotificationChannel(notificationManager,
|
||||||
|
NotificationUtils.NOTIFICATION_CHANNEL_CALLS, context.getResources()
|
||||||
|
.getString(R
|
||||||
|
.string.nc_notification_channel_calls), context.getResources()
|
||||||
|
.getString
|
||||||
|
(R.string.nc_notification_channel_calls_description), true,
|
||||||
|
NotificationManager.IMPORTANCE_HIGH, soundUri);
|
||||||
|
|
||||||
|
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_CALLS);
|
||||||
|
} else {
|
||||||
|
NotificationUtils.createNotificationChannel(notificationManager,
|
||||||
|
NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES, context.getResources()
|
||||||
|
.getString(R
|
||||||
|
.string.nc_notification_channel_messages), context.getResources()
|
||||||
|
.getString
|
||||||
|
(R.string.nc_notification_channel_messages_description), true,
|
||||||
|
NotificationManager.IMPORTANCE_DEFAULT, soundUri);
|
||||||
|
|
||||||
|
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationBuilder.setGroup(Long.toString(crc32.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationBuilder.setContentIntent(pendingIntent);
|
||||||
|
|
||||||
|
String stringForCrc = decryptedPushMessage.getSubject() + " " + signatureVerification
|
||||||
|
.getUserEntity().getDisplayName() + " " + signatureVerification.getUserEntity
|
||||||
|
().getBaseUrl();
|
||||||
|
|
||||||
|
crc32 = new CRC32();
|
||||||
|
crc32.update(stringForCrc.getBytes());
|
||||||
|
|
||||||
|
if (notificationManager != null) {
|
||||||
|
notificationManager.notify((int) crc32.getValue(), notificationBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (NoSuchAlgorithmException e1) {
|
||||||
|
Log.d(TAG, "No proper algorithm to decrypt the message " + e1.getLocalizedMessage());
|
||||||
|
} catch (NoSuchPaddingException e1) {
|
||||||
|
Log.d(TAG, "No proper padding to decrypt the message " + e1.getLocalizedMessage());
|
||||||
|
} catch (InvalidKeyException e1) {
|
||||||
|
Log.d(TAG, "Invalid private key " + e1.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Log.d(TAG, "Something went very wrong" + exception.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result.SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ import android.support.annotation.Nullable;
|
|||||||
import com.evernote.android.job.Job;
|
import com.evernote.android.job.Job;
|
||||||
import com.evernote.android.job.JobCreator;
|
import com.evernote.android.job.JobCreator;
|
||||||
import com.nextcloud.talk.jobs.AccountRemovalJob;
|
import com.nextcloud.talk.jobs.AccountRemovalJob;
|
||||||
|
import com.nextcloud.talk.jobs.NotificationJob;
|
||||||
import com.nextcloud.talk.jobs.PushRegistrationJob;
|
import com.nextcloud.talk.jobs.PushRegistrationJob;
|
||||||
|
|
||||||
public class MagicJobCreator implements JobCreator {
|
public class MagicJobCreator implements JobCreator {
|
||||||
@ -39,6 +40,8 @@ public class MagicJobCreator implements JobCreator {
|
|||||||
return new PushRegistrationJob();
|
return new PushRegistrationJob();
|
||||||
case AccountRemovalJob.TAG:
|
case AccountRemovalJob.TAG:
|
||||||
return new AccountRemovalJob();
|
return new AccountRemovalJob();
|
||||||
|
case NotificationJob.TAG:
|
||||||
|
return new NotificationJob();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,11 @@ public class Room {
|
|||||||
return (RoomType.ROOM_PUBLIC_CALL.equals(type));
|
return (RoomType.ROOM_PUBLIC_CALL.equals(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGuest() {
|
||||||
|
return (Participant.ParticipantType.GUEST.equals(participantType) ||
|
||||||
|
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participantType));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canModerate() {
|
public boolean canModerate() {
|
||||||
return (Participant.ParticipantType.OWNER.equals(participantType)
|
return (Participant.ParticipantType.OWNER.equals(participantType)
|
||||||
|| Participant.ParticipantType.MODERATOR.equals(participantType));
|
|| Participant.ParticipantType.MODERATOR.equals(participantType));
|
||||||
|
@ -21,43 +21,14 @@
|
|||||||
package com.nextcloud.talk.services.firebase;
|
package com.nextcloud.talk.services.firebase;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Base64;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
import com.evernote.android.job.JobRequest;
|
||||||
|
import com.evernote.android.job.util.support.PersistableBundleCompat;
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.jobs.NotificationJob;
|
||||||
import com.nextcloud.talk.activities.CallActivity;
|
|
||||||
import com.nextcloud.talk.models.SignatureVerification;
|
|
||||||
import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
|
|
||||||
import com.nextcloud.talk.models.json.push.PushMessage;
|
|
||||||
import com.nextcloud.talk.utils.NotificationUtils;
|
|
||||||
import com.nextcloud.talk.utils.PushUtils;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||||
|
|
||||||
import org.parceler.Parcels;
|
|
||||||
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.zip.CRC32;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
|
|
||||||
public class MagicFirebaseMessagingService extends FirebaseMessagingService {
|
public class MagicFirebaseMessagingService extends FirebaseMessagingService {
|
||||||
private static final String TAG = "MagicFirebaseMessagingService";
|
private static final String TAG = "MagicFirebaseMessagingService";
|
||||||
|
|
||||||
@ -65,149 +36,17 @@ public class MagicFirebaseMessagingService extends FirebaseMessagingService {
|
|||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||||
if (remoteMessage.getData() != null) {
|
if (remoteMessage.getData() != null) {
|
||||||
try {
|
PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat();
|
||||||
PushMessage pushMessage = new PushMessage();
|
persistableBundleCompat.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, remoteMessage.getData().get
|
||||||
pushMessage.setSubject(remoteMessage.getData().get("subject"));
|
("subject"));
|
||||||
pushMessage.setSignature(remoteMessage.getData().get("signature"));
|
persistableBundleCompat.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, remoteMessage.getData().get
|
||||||
|
("signature"));
|
||||||
byte[] base64DecodedSubject = android.util.Base64.decode(pushMessage.getSubject(), Base64.DEFAULT);
|
new JobRequest.Builder(NotificationJob.TAG)
|
||||||
byte[] base64DecodedSignature = android.util.Base64.decode(pushMessage.getSignature(), Base64.DEFAULT);
|
.addExtras(persistableBundleCompat)
|
||||||
PushUtils pushUtils = new PushUtils();
|
.setUpdateCurrent(false)
|
||||||
PrivateKey privateKey = (PrivateKey) pushUtils.readKeyFromFile(false);
|
.startNow()
|
||||||
|
.build()
|
||||||
try {
|
.schedule();
|
||||||
SignatureVerification signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
|
|
||||||
base64DecodedSubject);
|
|
||||||
|
|
||||||
if (signatureVerification.isSignatureValid()) {
|
|
||||||
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
|
||||||
byte[] decryptedSubject = cipher.doFinal(base64DecodedSubject);
|
|
||||||
DecryptedPushMessage decryptedPushMessage = LoganSquare.parse(new String(decryptedSubject),
|
|
||||||
DecryptedPushMessage.class);
|
|
||||||
|
|
||||||
if (decryptedPushMessage.getApp().equals("spreed")) {
|
|
||||||
int smallIcon;
|
|
||||||
Bitmap largeIcon;
|
|
||||||
String category = "";
|
|
||||||
int priority = Notification.PRIORITY_DEFAULT;
|
|
||||||
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
|
||||||
|
|
||||||
Intent intent = new Intent(this, CallActivity.class);
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
|
|
||||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(signatureVerification
|
|
||||||
.getUserEntity()));
|
|
||||||
bundle.putBoolean("fromNotification", true);
|
|
||||||
intent.putExtras(bundle);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(this,
|
|
||||||
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
|
|
||||||
NotificationManager notificationManager =
|
|
||||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
switch (decryptedPushMessage.getType()) {
|
|
||||||
case "call":
|
|
||||||
smallIcon = R.drawable.ic_call_black_24dp;
|
|
||||||
category = Notification.CATEGORY_CALL;
|
|
||||||
priority = Notification.PRIORITY_HIGH;
|
|
||||||
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
|
||||||
break;
|
|
||||||
case "room":
|
|
||||||
smallIcon = R.drawable.ic_notifications_black_24dp;
|
|
||||||
category = Notification.CATEGORY_CALL;
|
|
||||||
priority = Notification.PRIORITY_HIGH;
|
|
||||||
break;
|
|
||||||
case "chat":
|
|
||||||
smallIcon = R.drawable.ic_chat_black_24dp;
|
|
||||||
category = Notification.CATEGORY_MESSAGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
smallIcon = R.drawable.ic_logo;
|
|
||||||
}
|
|
||||||
|
|
||||||
largeIcon = BitmapFactory.decodeResource(getResources(), smallIcon);
|
|
||||||
CRC32 crc32 = new CRC32();
|
|
||||||
|
|
||||||
Notification.Builder notificationBuilder = new Notification.Builder(this)
|
|
||||||
.setLargeIcon(largeIcon)
|
|
||||||
.setSmallIcon(smallIcon)
|
|
||||||
.setCategory(category)
|
|
||||||
.setPriority(priority)
|
|
||||||
.setWhen(Calendar.getInstance().getTimeInMillis())
|
|
||||||
.setShowWhen(true)
|
|
||||||
.setSubText(signatureVerification.getUserEntity().getDisplayName())
|
|
||||||
.setContentTitle(decryptedPushMessage.getSubject())
|
|
||||||
.setSound(soundUri)
|
|
||||||
.setAutoCancel(true);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
// This method should exist since API 21, but some phones don't have it
|
|
||||||
// So as a safeguard, we don't use it until 23
|
|
||||||
notificationBuilder.setColor(getResources().getColor(R.color.colorPrimary));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
|
||||||
|
|
||||||
String groupName = String.format(getResources().getString(R.string
|
|
||||||
.nc_notification_channel), signatureVerification.getUserEntity()
|
|
||||||
.getDisplayName(), signatureVerification.getUserEntity().getBaseUrl());
|
|
||||||
crc32.update(groupName.getBytes());
|
|
||||||
|
|
||||||
NotificationUtils.createNotificationChannelGroup(notificationManager,
|
|
||||||
Long.toString(crc32.getValue()),
|
|
||||||
groupName);
|
|
||||||
|
|
||||||
if (category.equals(Notification.CATEGORY_CALL)) {
|
|
||||||
NotificationUtils.createNotificationChannel(notificationManager,
|
|
||||||
NotificationUtils.NOTIFICATION_CHANNEL_CALLS, getResources().getString(R
|
|
||||||
.string.nc_notification_channel_calls), getResources().getString
|
|
||||||
(R.string.nc_notification_channel_calls_description), true,
|
|
||||||
NotificationManager.IMPORTANCE_HIGH, soundUri);
|
|
||||||
|
|
||||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_CALLS);
|
|
||||||
} else {
|
|
||||||
NotificationUtils.createNotificationChannel(notificationManager,
|
|
||||||
NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES, getResources().getString(R
|
|
||||||
.string.nc_notification_channel_messages), getResources().getString
|
|
||||||
(R.string.nc_notification_channel_messages_description), true,
|
|
||||||
NotificationManager.IMPORTANCE_DEFAULT, soundUri);
|
|
||||||
|
|
||||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES);
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationBuilder.setGroup(Long.toString(crc32.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationBuilder.setContentIntent(pendingIntent);
|
|
||||||
|
|
||||||
String stringForCrc = decryptedPushMessage.getSubject() + " " + signatureVerification
|
|
||||||
.getUserEntity().getDisplayName() + " " + signatureVerification.getUserEntity
|
|
||||||
().getBaseUrl();
|
|
||||||
|
|
||||||
crc32 = new CRC32();
|
|
||||||
crc32.update(stringForCrc.getBytes());
|
|
||||||
|
|
||||||
if (notificationManager != null) {
|
|
||||||
notificationManager.notify((int) crc32.getValue(), notificationBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (NoSuchAlgorithmException e1) {
|
|
||||||
Log.d(TAG, "No proper algorithm to decrypt the message " + e1.getLocalizedMessage());
|
|
||||||
} catch (NoSuchPaddingException e1) {
|
|
||||||
Log.d(TAG, "No proper padding to decrypt the message " + e1.getLocalizedMessage());
|
|
||||||
} catch (InvalidKeyException e1) {
|
|
||||||
Log.d(TAG, "Invalid private key " + e1.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception exception) {
|
|
||||||
Log.d(TAG, "Something went very wrong" + exception.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "The data we received was empty");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class BundleKeys {
|
|||||||
public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
|
public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
|
||||||
public static final String KEY_ROOM = "KEY_ROOM";
|
public static final String KEY_ROOM = "KEY_ROOM";
|
||||||
public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
|
public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
|
||||||
public static final String KEY_IS_SHARE = "KEY_IS_SHARE";
|
public static final String KEY_MENU_TYPE = "KEY_MENU_TYPE";
|
||||||
public static final String KEY_SHARE_INTENT = "KEY_SHARE_INTENT";
|
public static final String KEY_SHARE_INTENT = "KEY_SHARE_INTENT";
|
||||||
public static final String KEY_APP_ITEM_PACKAGE_NAME = "KEY_APP_ITEM_PACKAGE_NAME";
|
public static final String KEY_APP_ITEM_PACKAGE_NAME = "KEY_APP_ITEM_PACKAGE_NAME";
|
||||||
public static final String KEY_APP_ITEM_NAME = "KEY_APP_ITEM_NAME";
|
public static final String KEY_APP_ITEM_NAME = "KEY_APP_ITEM_NAME";
|
||||||
@ -38,4 +38,8 @@ public class BundleKeys {
|
|||||||
public static final String KEY_USER_ENTITY = "KEY_USER_ENTITY";
|
public static final String KEY_USER_ENTITY = "KEY_USER_ENTITY";
|
||||||
public static final String KEY_NEW_CONVERSATION = "KEY_NEW_CONVERSATION";
|
public static final String KEY_NEW_CONVERSATION = "KEY_NEW_CONVERSATION";
|
||||||
public static final String KEY_IS_PUBLIC_CALL = "KEY_IS_PUBLIC_CALL";
|
public static final String KEY_IS_PUBLIC_CALL = "KEY_IS_PUBLIC_CALL";
|
||||||
|
public static final String KEY_CALL_URL = "KEY_CALL_URL";
|
||||||
|
public static final String KEY_MODIFIED_BASE_URL = "KEY_MODIFIED_BASE_URL";
|
||||||
|
public static final String KEY_NOTIFICATION_SUBJECT = "KEY_NOTIFICATION_SUBJECT";
|
||||||
|
public static final String KEY_NOTIFICATION_SIGNATURE = "KEY_NOTIFICATION_SIGNATURE";
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
<string name="nc_never">Never joined</string>
|
<string name="nc_never">Never joined</string>
|
||||||
<string name="nc_search">Search</string>
|
<string name="nc_search">Search</string>
|
||||||
<string name="nc_new_conversation">Create a new conversation</string>
|
|
||||||
|
|
||||||
<string name="nc_certificate_dialog_title">Check out the certificate</string>
|
<string name="nc_certificate_dialog_title">Check out the certificate</string>
|
||||||
<string name="nc_certificate_dialog_text">Do you trust the until now unknown SSL certificate, issued by %1$s for %2$s, valid from %3$s to %4$s?</string>
|
<string name="nc_certificate_dialog_text">Do you trust the until now unknown SSL certificate, issued by %1$s for %2$s, valid from %3$s to %4$s?</string>
|
||||||
@ -61,6 +60,7 @@
|
|||||||
<string name="nc_no_proxy">No proxy</string>
|
<string name="nc_no_proxy">No proxy</string>
|
||||||
<string name="nc_username">Username</string>
|
<string name="nc_username">Username</string>
|
||||||
<string name="nc_password">Password</string>
|
<string name="nc_password">Password</string>
|
||||||
|
<string name="nc_conversation_link">Conversation link</string>
|
||||||
<string name="nc_new_password">New password</string>
|
<string name="nc_new_password">New password</string>
|
||||||
<string name="nc_wrong_password">Wrong password</string>
|
<string name="nc_wrong_password">Wrong password</string>
|
||||||
<string name="nc_about">About</string>
|
<string name="nc_about">About</string>
|
||||||
@ -83,6 +83,9 @@
|
|||||||
<string name="nc_make_call_public">Make call public</string>
|
<string name="nc_make_call_public">Make call public</string>
|
||||||
<string name="nc_make_call_private">Make call private</string>
|
<string name="nc_make_call_private">Make call private</string>
|
||||||
<string name="nc_delete_call">Delete call</string>
|
<string name="nc_delete_call">Delete call</string>
|
||||||
|
<string name="nc_new_conversation">Start a new conversation</string>
|
||||||
|
<string name="nc_join_via_link">Join via link</string>
|
||||||
|
<string name="nc_join_via_web">Join via web</string>
|
||||||
|
|
||||||
<!-- Contacts -->
|
<!-- Contacts -->
|
||||||
<string name="nc_select_contacts">Select contacts</string>
|
<string name="nc_select_contacts">Select contacts</string>
|
||||||
@ -115,11 +118,14 @@
|
|||||||
|
|
||||||
<!-- Bottom sheet menu -->
|
<!-- Bottom sheet menu -->
|
||||||
<string name="nc_failed_to_perform_operation">Sorry, something went wrong!</string>
|
<string name="nc_failed_to_perform_operation">Sorry, something went wrong!</string>
|
||||||
|
<string name="nc_failed_signaling_settings">Target server does not support joining public rooms via mobile phones.
|
||||||
|
You may attempt to join the call via web browser.</string>
|
||||||
<string name="nc_all_ok_operation">OK, all done!</string>
|
<string name="nc_all_ok_operation">OK, all done!</string>
|
||||||
<string name="nc_ok">OK</string>
|
<string name="nc_ok">OK</string>
|
||||||
<string name="nc_call_name">Call name</string>
|
<string name="nc_call_name">Call name</string>
|
||||||
<string name="nc_proceed">Proceed</string>
|
<string name="nc_proceed">Proceed</string>
|
||||||
<string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
|
<string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
|
||||||
|
<string name="nc_wrong_link">Conversation link is not valid</string>
|
||||||
<string name="nc_share_text">Hello,\n\nI would like you to join a call with me.\n\nYou can join this call via
|
<string name="nc_share_text">Hello,\n\nI would like you to join a call with me.\n\nYou can join this call via
|
||||||
%1$s/index.php/call/%2$s</string>
|
%1$s/index.php/call/%2$s</string>
|
||||||
<string name="nc_talk_soon">\n\nTalk soon,\n %1$s</string>
|
<string name="nc_talk_soon">\n\nTalk soon,\n %1$s</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user