diff --git a/app/build.gradle b/app/build.gradle
index 47ea25db2..2496da965 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -215,6 +215,8 @@ dependencies {
implementation 'com.github.natario1:Autocomplete:v1.1.0'
+ implementation 'com.novoda:merlin:1.2.0'
+
implementation 'com.github.Kennyc1012:BottomSheet:2.4.1'
implementation 'com.github.mario:PopupBubble:a365177d96'
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 22facacdf..209b743bf 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -95,5 +95,9 @@
+
+
diff --git a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
index bd2b15e33..f50b1de30 100644
--- a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
+++ b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
@@ -50,6 +50,7 @@ import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache;
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule;
import com.nextcloud.talk.utils.database.user.UserModule;
+import com.nextcloud.talk.utils.singletons.MerlinTheWizard;
import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
import com.vanniktech.emoji.EmojiManager;
import com.vanniktech.emoji.twitter.TwitterEmojiProvider;
@@ -150,6 +151,8 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Lif
OneTimeWorkRequest capabilitiesUpdateWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class).build();
OneTimeWorkRequest signalingSettingsWork = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class).build();
+ new MerlinTheWizard().initMerlin();
+
WorkManager.getInstance().enqueue(pushRegistrationWork);
WorkManager.getInstance().enqueue(accountRemovalWork);
WorkManager.getInstance().enqueue(capabilitiesUpdateWork);
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
index b3e131e24..498b07498 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
@@ -582,7 +582,6 @@ public class CallController extends BaseController {
public void onEnableSpeakerphoneClick() {
if (audioManager != null) {
audioManager.toggleUseSpeakerphone();
- //callControlEnableSpeaker.flipSilently(!callControlEnableSpeaker.isFlipped());
}
}
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java
index 6a3491b3e..fc3f02c16 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java
@@ -68,6 +68,7 @@ import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences;
import com.nextcloud.talk.utils.preferences.MagicUserInputModule;
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
+import com.nextcloud.talk.utils.singletons.MerlinTheWizard;
import com.yarolegovich.lovelydialog.LovelySaveStateHandler;
import com.yarolegovich.lovelydialog.LovelyStandardDialog;
import com.yarolegovich.mp.*;
@@ -361,6 +362,12 @@ public class SettingsController extends BaseController {
private void removeCurrentAccount() {
boolean otherUserExists = userUtils.scheduleUserForDeletionWithId(currentUser.getId());
+ if (otherUserExists) {
+ new MerlinTheWizard().initMerlin();
+ } else {
+ new MerlinTheWizard().getMerlin().unbind();
+ }
+
OneTimeWorkRequest accountRemovalWork = new OneTimeWorkRequest.Builder(AccountRemovalWorker.class).build();
WorkManager.getInstance().enqueue(accountRemovalWork);
diff --git a/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java b/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java
new file mode 100644
index 000000000..76406661d
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java
@@ -0,0 +1,36 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic
+ *
+ * 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 .
+ */
+
+package com.nextcloud.talk.events;
+
+import lombok.Data;
+
+@Data
+public class NetworkEvent {
+ public enum NetworkConnectionEvent {
+ NETWORK_CONNECTED, NETWORK_DISCONNECTED
+ }
+
+ private final NetworkConnectionEvent networkConnectionEvent;
+
+ public NetworkEvent(NetworkConnectionEvent networkConnectionEvent) {
+ this.networkConnectionEvent = networkConnectionEvent;
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/singletons/MerlinTheWizard.java b/app/src/main/java/com/nextcloud/talk/utils/singletons/MerlinTheWizard.java
new file mode 100644
index 000000000..f75966882
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/singletons/MerlinTheWizard.java
@@ -0,0 +1,112 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic
+ *
+ * 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 .
+ */
+
+package com.nextcloud.talk.utils.singletons;
+
+import android.content.Context;
+import android.database.Observable;
+import android.util.Log;
+import autodagger.AutoInjector;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
+import com.nextcloud.talk.events.NetworkEvent;
+import com.nextcloud.talk.models.database.User;
+import com.nextcloud.talk.models.database.UserEntity;
+import com.nextcloud.talk.utils.database.user.UserUtils;
+import com.novoda.merlin.*;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Consumer;
+import io.requery.Persistable;
+import io.requery.reactivex.ReactiveEntityStore;
+import io.requery.reactivex.ReactiveResult;
+import io.requery.util.ObservableList;
+import org.greenrobot.eventbus.EventBus;
+
+import javax.inject.Inject;
+import java.util.List;
+
+@AutoInjector(NextcloudTalkApplication.class)
+public class MerlinTheWizard {
+ private static Merlin merlin;
+ private static MerlinsBeard merlinsBeard;
+
+ private UserEntity currentUserEntity;
+
+ @Inject
+ EventBus eventBus;
+
+ @Inject
+ Context context;
+
+ @Inject
+ UserUtils userUtils;
+
+ public MerlinTheWizard() {
+ NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+ }
+
+ public void initMerlin() {
+ if (userUtils.anyUserExists() && (currentUserEntity == null ||
+ (userUtils.getCurrentUser().getId() != currentUserEntity.getId()))) {
+ currentUserEntity = userUtils.getCurrentUser();
+ setupMerlinForCurrentUserEntity();
+ }
+ }
+
+ public Merlin getMerlin() {
+ return merlin;
+ }
+
+ public MerlinsBeard getMerlinsBeard() {
+ return merlinsBeard;
+ }
+
+
+ private void setupMerlinForCurrentUserEntity() {
+ Endpoint endpoint = Endpoint.from(currentUserEntity.getBaseUrl() + "/index.php/204");
+ ResponseCodeValidator responseCodeValidator =
+ new ResponseCodeValidator.CaptivePortalResponseCodeValidator();
+
+ if (merlin != null) {
+ merlin.unbind();
+ }
+
+ merlin = new Merlin.Builder().withAllCallbacks().withEndpoint(endpoint).withResponseCodeValidator(responseCodeValidator).build(context);
+
+ merlin.bind();
+
+ merlinsBeard = new MerlinsBeard.Builder().withEndpoint(Endpoint.from(currentUserEntity.getBaseUrl() +
+ "/index.php/204")).withResponseCodeValidator(new ResponseCodeValidator.CaptivePortalResponseCodeValidator()).build(context);
+
+ merlin.registerConnectable(new Connectable() {
+ @Override
+ public void onConnect() {
+ eventBus.post(new NetworkEvent(NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED));
+ }
+ });
+
+ merlin.registerDisconnectable(new Disconnectable() {
+ @Override
+ public void onDisconnect() {
+ eventBus.post(new NetworkEvent(NetworkEvent.NetworkConnectionEvent.NETWORK_DISCONNECTED));
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java
index de6e86b7f..e1e85fa08 100644
--- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java
+++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java
@@ -20,21 +20,29 @@
package com.nextcloud.talk.webrtc;
+import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import autodagger.AutoInjector;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
+import com.nextcloud.talk.events.NetworkEvent;
import com.nextcloud.talk.events.WebSocketCommunicationEvent;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.signaling.NCMessageWrapper;
import com.nextcloud.talk.models.json.signaling.NCSignalingMessage;
import com.nextcloud.talk.models.json.websocket.*;
import com.nextcloud.talk.utils.MagicMap;
+import com.nextcloud.talk.utils.singletons.MerlinTheWizard;
+import com.novoda.merlin.Endpoint;
+import com.novoda.merlin.MerlinsBeard;
+import com.novoda.merlin.ResponseCodeValidator;
import okhttp3.*;
import okio.ByteString;
import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
import javax.inject.Inject;
import java.io.IOException;
@@ -53,6 +61,9 @@ public class MagicWebSocketInstance extends WebSocketListener {
@Inject
EventBus eventBus;
+ @Inject
+ Context context;
+
private UserEntity conversationUser;
private String webSocketTicket;
private String resumeId;
@@ -71,6 +82,7 @@ public class MagicWebSocketInstance extends WebSocketListener {
private HashMap displayNameHashMap;
private HashMap userIdSesssionHashMap;
+ private MerlinTheWizard merlinTheWizard;
private List messagesQueue = new ArrayList<>();
MagicWebSocketInstance(UserEntity conversationUser, String connectionUrl, String webSocketTicket) {
@@ -84,7 +96,10 @@ public class MagicWebSocketInstance extends WebSocketListener {
this.userIdSesssionHashMap = new HashMap<>();
magicMap = new MagicMap();
+ merlinTheWizard = new MerlinTheWizard();
connected = false;
+ eventBus.register(this);
+
restartWebSocket();
}
@@ -107,6 +122,7 @@ public class MagicWebSocketInstance extends WebSocketListener {
}
private void closeWebSocket(WebSocket webSocket) {
+ connected = false;
webSocket.close(1000, null);
webSocket.cancel();
messagesQueue = new ArrayList<>();
@@ -116,9 +132,11 @@ public class MagicWebSocketInstance extends WebSocketListener {
private void restartWebSocket() {
reconnecting = true;
- Request request = new Request.Builder().url(connectionUrl).build();
- okHttpClient.newWebSocket(request, this);
- restartCount++;
+ if (merlinTheWizard.getMerlinsBeard().hasInternetAccess()) {
+ Request request = new Request.Builder().url(connectionUrl).build();
+ okHttpClient.newWebSocket(request, this);
+ restartCount++;
+ }
}
@Override
@@ -335,4 +353,12 @@ public class MagicWebSocketInstance extends WebSocketListener {
public String getSessionForUserId(String userId) {
return userIdSesssionHashMap.get(userId);
}
+
+ @Subscribe(threadMode = ThreadMode.BACKGROUND)
+ public void onMessageEvent(NetworkEvent networkEvent) {
+ if (networkEvent.getNetworkConnectionEvent().equals(NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED) && !isConnected()) {
+ restartWebSocket();
+ }
+ }
+
}
diff --git a/app/src/main/res/layout/controller_call.xml b/app/src/main/res/layout/controller_call.xml
index 235bb1e2e..9e86af0b4 100644
--- a/app/src/main/res/layout/controller_call.xml
+++ b/app/src/main/res/layout/controller_call.xml
@@ -155,6 +155,7 @@