Commit cc94abe8 authored by Yusuke Iwaki's avatar Yusuke Iwaki

remove ServerConfig

parent b9a14855
......@@ -5,12 +5,22 @@ import android.content.Intent;
import chat.rocket.android.activity.AddServerActivity;
import chat.rocket.android.activity.LoginActivity;
import chat.rocket.android.activity.MainActivity;
/**
* utility class for launching Activity.
*/
public class LaunchUtil {
/**
* launch MainActivity with proper flags.
*/
public static void showMainActivity(Context context) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
}
/**
* launch AddServerActivity with proper flags.
*/
......@@ -23,10 +33,10 @@ public class LaunchUtil {
/**
* launch ServerConfigActivity with proper flags.
*/
public static void showLoginActivity(Context context, String serverCondigId) {
public static void showLoginActivity(Context context, String hostname) {
Intent intent = new Intent(context, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("serverConfigId", serverCondigId);
intent.putExtra("hostname", hostname);
context.startActivity(intent);
}
}
......@@ -7,8 +7,9 @@ import io.realm.Realm;
import io.realm.RealmConfiguration;
import java.util.List;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.service.ServerInfo;
import chat.rocket.android.wrappers.InstabugWrapper;
/**
......@@ -23,10 +24,9 @@ public class RocketChatApplication extends MultiDexApplication {
Realm.setDefaultConfiguration(
new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build());
List<ServerConfig> configs = RealmStore.getDefault().executeTransactionForReadResults(realm ->
realm.where(ServerConfig.class).isNotNull(ServerConfig.SESSION).findAll());
for (ServerConfig config : configs) {
RealmStore.put(config.getServerConfigId());
List<ServerInfo> serverInfoList = ConnectivityManager.getInstance(this).getServerList();
for (ServerInfo serverInfo : serverInfoList) {
RealmStore.put(serverInfo.hostname);
}
Stetho.initialize(Stetho.newInitializerBuilder(this)
......
......@@ -9,7 +9,7 @@ import java.util.UUID;
* sharedpreference-based cache.
*/
public class RocketChatCache {
public static final String KEY_SELECTED_SERVER_CONFIG_ID = "selectedServerConfigId";
public static final String KEY_SELECTED_SERVER_HOSTNAME = "selectedServerHostname";
public static final String KEY_SELECTED_ROOM_ID = "selectedRoomId";
private static final String KEY_PUSH_ID = "pushId";
......
......@@ -5,61 +5,50 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.Nullable;
import chat.rocket.android.LaunchUtil;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.push.PushConstants;
import chat.rocket.android.push.PushNotificationHandler;
import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.RocketChatService;
import chat.rocket.android.service.ConnectivityManager;
import icepick.State;
abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
@State protected String serverConfigId;
@State protected String hostname;
@State protected String roomId;
SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener =
(sharedPreferences, key) -> {
if (RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID.equals(key)) {
updateServerConfigIdIfNeeded(sharedPreferences);
if (RocketChatCache.KEY_SELECTED_SERVER_HOSTNAME.equals(key)) {
updateHostnameIfNeeded(sharedPreferences);
} else if (RocketChatCache.KEY_SELECTED_ROOM_ID.equals(key)) {
updateRoomIdIfNeeded(sharedPreferences);
}
};
private RealmListObserver<ServerConfig> unconfiguredServersObserver =
RealmStore.getDefault()
.createListObserver(realm ->
realm.where(ServerConfig.class).isNotNull(ServerConfig.SESSION).findAll())
.setOnUpdateListener(results -> {
if (results.isEmpty()) {
LaunchUtil.showAddServerActivity(this);
}
});
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
onIntent(getIntent());
handleIntent(getIntent());
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
onIntent(intent);
handleIntent(intent);
}
private void onIntent(Intent intent) {
private void handleIntent(Intent intent) {
if (intent == null) {
return;
}
if (intent.hasExtra(PushConstants.SERVER_CONFIG_ID)) {
if (intent.hasExtra(PushConstants.HOSTNAME)) {
SharedPreferences.Editor editor = RocketChatCache.get(this).edit();
editor.putString(RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID,
intent.getStringExtra(PushConstants.SERVER_CONFIG_ID));
editor.putString(RocketChatCache.KEY_SELECTED_SERVER_HOSTNAME,
intent.getStringExtra(PushConstants.HOSTNAME));
if (intent.hasExtra(PushConstants.ROOM_ID)) {
editor.putString(RocketChatCache.KEY_SELECTED_ROOM_ID,
......@@ -74,24 +63,23 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
}
}
private void updateServerConfigIdIfNeeded(SharedPreferences prefs) {
String newServerConfigId = prefs.getString(RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID, null);
if (serverConfigId == null) {
if (newServerConfigId != null && assertServerConfigExists(newServerConfigId, prefs)) {
updateServerConfigId(newServerConfigId);
private void updateHostnameIfNeeded(SharedPreferences prefs) {
String newHostname = prefs.getString(RocketChatCache.KEY_SELECTED_SERVER_HOSTNAME, null);
if (hostname == null) {
if (newHostname != null && assertServerRealmStoreExists(newHostname, prefs)) {
updateHostname(newHostname);
}
} else {
if (!serverConfigId.equals(newServerConfigId)
&& assertServerConfigExists(newServerConfigId, prefs)) {
updateServerConfigId(newServerConfigId);
if (!hostname.equals(newHostname) && assertServerRealmStoreExists(newHostname, prefs)) {
updateHostname(newHostname);
}
}
}
private boolean assertServerConfigExists(String serverConfigId, SharedPreferences prefs) {
if (RealmStore.get(serverConfigId) == null) {
private boolean assertServerRealmStoreExists(String hostname, SharedPreferences prefs) {
if (RealmStore.get(hostname) == null) {
prefs.edit()
.remove(RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID)
.remove(RocketChatCache.KEY_SELECTED_SERVER_HOSTNAME)
.remove(RocketChatCache.KEY_SELECTED_ROOM_ID)
.apply();
return false;
......@@ -99,9 +87,9 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
return true;
}
private void updateServerConfigId(String serverConfigId) {
this.serverConfigId = serverConfigId;
onServerConfigIdUpdated();
private void updateHostname(String hostname) {
this.hostname = hostname;
onHostnameUpdated();
}
private void updateRoomIdIfNeeded(SharedPreferences prefs) {
......@@ -118,11 +106,11 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
}
private boolean assertRoomSubscriptionExists(String roomId, SharedPreferences prefs) {
if (!assertServerConfigExists(serverConfigId, prefs)) {
if (!assertServerRealmStoreExists(hostname, prefs)) {
return false;
}
RoomSubscription room = RealmStore.get(serverConfigId).executeTransactionForRead(realm ->
RoomSubscription room = RealmStore.get(hostname).executeTransactionForRead(realm ->
realm.where(RoomSubscription.class).equalTo(RoomSubscription.ROOM_ID, roomId).findFirst());
if (room == null) {
prefs.edit()
......@@ -138,7 +126,7 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
onRoomIdUpdated();
}
protected void onServerConfigIdUpdated() {
protected void onHostnameUpdated() {
}
protected void onRoomIdUpdated() {
......@@ -147,11 +135,10 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
@Override
protected void onResume() {
super.onResume();
RocketChatService.keepAlive(this);
unconfiguredServersObserver.sub();
ConnectivityManager.getInstance(getApplicationContext()).keepAliveServer();
SharedPreferences prefs = RocketChatCache.get(this);
updateServerConfigIdIfNeeded(prefs);
updateHostnameIfNeeded(prefs);
updateRoomIdIfNeeded(prefs);
prefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}
......@@ -161,7 +148,6 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
SharedPreferences prefs = RocketChatCache.get(this);
prefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
unconfiguredServersObserver.unsub();
super.onPause();
}
......
......@@ -2,72 +2,18 @@ package chat.rocket.android.activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import java.util.UUID;
import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.fragment.server_config.InputHostnameFragment;
import chat.rocket.android.fragment.server_config.WaitingFragment;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.fragment.add_server.InputHostnameFragment;
public class AddServerActivity extends AbstractFragmentActivity {
private String serverConfigId;
private RealmListObserver<ServerConfig> configuredServersObserver = RealmStore.getDefault()
.createListObserver(
realm -> realm.where(ServerConfig.class).isNotNull(ServerConfig.SESSION).findAll())
.setOnUpdateListener(results -> {
if (!results.isEmpty()) {
RocketChatCache.get(this).edit()
.putString(RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID, serverConfigId)
.apply();
finish();
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
});
private RealmObjectObserver<ServerConfig> targetServerConfigObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.ID, serverConfigId))
.setOnUpdateListener(config -> {
if (config == null || config.getState() == ServerConfig.STATE_CONNECTION_ERROR) {
showFragment(new InputHostnameFragment());
} else {
showFragment(
WaitingFragment.create(getString(R.string.add_server_activity_waiting_server)));
}
});
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_screen);
setupServerConfigId();
}
private void setupServerConfigId() {
ServerConfig config = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class).isNull(ServerConfig.HOSTNAME).findFirst());
if (config != null) {
serverConfigId = config.getServerConfigId();
return;
}
config = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class)
.equalTo(ServerConfig.STATE, ServerConfig.STATE_CONNECTION_ERROR).findFirst());
if (config != null) {
serverConfigId = config.getServerConfigId();
return;
}
serverConfigId = UUID.randomUUID().toString();
showFragment(new InputHostnameFragment());
}
@Override
......@@ -75,41 +21,6 @@ public class AddServerActivity extends AbstractFragmentActivity {
return R.id.content;
}
@Override
protected void onResume() {
super.onResume();
configuredServersObserver.sub();
targetServerConfigObserver.sub();
}
@Override
protected void onPause() {
configuredServersObserver.unsub();
targetServerConfigObserver.unsub();
super.onPause();
}
@Override
protected void showFragment(Fragment fragment) {
injectServerConfigIdArgTo(fragment);
super.showFragment(fragment);
}
@Override
protected void showFragmentWithBackStack(Fragment fragment) {
injectServerConfigIdArgTo(fragment);
super.showFragmentWithBackStack(fragment);
}
private void injectServerConfigIdArgTo(Fragment fragment) {
Bundle args = fragment.getArguments();
if (args == null) {
args = new Bundle();
}
args.putString(ServerConfig.ID, serverConfigId);
fragment.setArguments(args);
}
@Override
protected void onBackPressedNotHandled() {
moveTaskToBack(true);
......
......@@ -7,14 +7,13 @@ import android.support.v4.app.Fragment;
import chat.rocket.android.R;
import chat.rocket.android.fragment.server_config.LoginFragment;
import chat.rocket.android.fragment.server_config.RetryConnectFragment;
import chat.rocket.android.fragment.server_config.RetryLoginFragment;
import chat.rocket.android.fragment.server_config.WaitingFragment;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.service.RocketChatService;
/**
......@@ -22,8 +21,7 @@ import chat.rocket.android.service.RocketChatService;
*/
public class LoginActivity extends AbstractFragmentActivity {
private String serverConfigId;
private RealmObjectObserver<ServerConfig> serverConfigErrorObserver;
private String hostname;
private RealmObjectObserver<Session> sessionObserver;
@Override
......@@ -41,50 +39,33 @@ public class LoginActivity extends AbstractFragmentActivity {
return;
}
serverConfigId = intent.getStringExtra(ServerConfig.ID);
if (TextUtils.isEmpty(serverConfigId)) {
hostname = intent.getStringExtra("hostname");
if (TextUtils.isEmpty(hostname)) {
finish();
return;
}
serverConfigErrorObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class)
.equalTo(ServerConfig.ID, serverConfigId)
.equalTo(ServerConfig.STATE, ServerConfig.STATE_CONNECTION_ERROR))
.setOnUpdateListener(this::onRenderServerConfigError);
sessionObserver = RealmStore.get(serverConfigId)
sessionObserver = RealmStore.get(hostname)
.createObjectObserver(Session::queryDefaultSession)
.setOnUpdateListener(this::onRenderServerConfigSession);
setContentView(R.layout.simple_screen);
showFragment(new WaitingFragment());
serverConfigErrorObserver.sub();
}
@Override
protected void onResume() {
super.onResume();
RocketChatService.keepAlive(this);
ConnectivityManager.getInstance(getApplicationContext()).keepAliveServer();
sessionObserver.sub();
}
@Override
protected void onDestroy() {
sessionObserver.unsub();
serverConfigErrorObserver.unsub();
super.onDestroy();
}
private void onRenderServerConfigError(ServerConfig config) {
if (config != null) {
sessionObserver.unsub();
showFragment(new RetryConnectFragment());
} else {
sessionObserver.sub();
}
}
private void onRenderServerConfigSession(Session session) {
if (session == null) {
showFragment(new LoginFragment());
......@@ -107,22 +88,22 @@ public class LoginActivity extends AbstractFragmentActivity {
@Override
protected void showFragment(Fragment fragment) {
injectServerConfigIdArgTo(fragment);
injectHostnameArgTo(fragment);
super.showFragment(fragment);
}
@Override
protected void showFragmentWithBackStack(Fragment fragment) {
injectServerConfigIdArgTo(fragment);
injectHostnameArgTo(fragment);
super.showFragmentWithBackStack(fragment);
}
private void injectServerConfigIdArgTo(Fragment fragment) {
private void injectHostnameArgTo(Fragment fragment) {
Bundle args = fragment.getArguments();
if (args == null) {
args = new Bundle();
}
args.putString(ServerConfig.ID, serverConfigId);
args.putString("hostname", hostname);
fragment.setArguments(args);
}
......
......@@ -17,7 +17,6 @@ import chat.rocket.android.fragment.chatroom.RoomFragment;
import chat.rocket.android.fragment.sidebar.SidebarMainFragment;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.model.internal.Session;
......@@ -25,6 +24,7 @@ import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.widget.RoomToolbar;
import hugo.weaving.DebugLog;
......@@ -53,6 +53,10 @@ public class MainActivity extends AbstractAuthedActivity {
if (roomId == null) {
showFragment(new HomeFragment());
}
if (shouldLaunchAddServerActivity()) {
LaunchUtil.showAddServerActivity(this);
}
}
@Override
......@@ -82,15 +86,15 @@ public class MainActivity extends AbstractAuthedActivity {
}
private void setUserOnlineIfServerAvailable() {
if (serverConfigId != null) {
new MethodCallHelper(this, serverConfigId).setUserPresence(User.STATUS_ONLINE)
if (hostname != null) {
new MethodCallHelper(this, hostname).setUserPresence(User.STATUS_ONLINE)
.continueWith(new LogcatIfError());
}
}
private void setUserAwayIfServerAvailable() {
if (serverConfigId != null) {
new MethodCallHelper(this, serverConfigId).setUserPresence(User.STATUS_AWAY)
if (hostname != null) {
new MethodCallHelper(this, hostname).setUserPresence(User.STATUS_AWAY)
.continueWith(new LogcatIfError());
}
}
......@@ -150,10 +154,14 @@ public class MainActivity extends AbstractAuthedActivity {
return false;
}
private boolean shouldLaunchAddServerActivity() {
return ConnectivityManager.getInstance(getApplicationContext()).getServerList().isEmpty();
}
@DebugLog
@Override
protected void onServerConfigIdUpdated() {
super.onServerConfigIdUpdated();
protected void onHostnameUpdated() {
super.onHostnameUpdated();
updateSessionObserver();
updateUnreadRoomSubscriptionObserver();
updateSidebarMainFragment();
......@@ -165,11 +173,11 @@ public class MainActivity extends AbstractAuthedActivity {
sessionObserver = null;
}
if (serverConfigId == null) {
if (hostname == null) {
return;
}
RealmHelper realmHelper = RealmStore.get(serverConfigId);
RealmHelper realmHelper = RealmStore.get(hostname);
if (realmHelper == null) {
return;
}
......@@ -185,7 +193,7 @@ public class MainActivity extends AbstractAuthedActivity {
private void onSessionChanged(@Nullable Session session) {
if (session == null) {
if (isForeground) {
LaunchUtil.showLoginActivity(this, serverConfigId);
LaunchUtil.showLoginActivity(this, hostname);
}
statusTicker.updateStatus(StatusTicker.STATUS_DISMISS, null);
} else if (!TextUtils.isEmpty(session.getError())) {
......@@ -193,17 +201,8 @@ public class MainActivity extends AbstractAuthedActivity {
Snackbar.make(findViewById(getLayoutContainerForFragment()),
R.string.fragment_retry_login_error_title, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.fragment_retry_login_retry_title, view ->
RealmStore.getDefault()
.executeTransaction(realm -> {
ServerConfig config = realm.where(ServerConfig.class)
.equalTo(ServerConfig.ID, serverConfigId).findFirst();
if (config != null
&& config.getState() == ServerConfig.STATE_CONNECTION_ERROR) {
config.setState(ServerConfig.STATE_READY);
}
return null;
}).continueWith(new LogcatIfError())));
ConnectivityManager.getInstance(getApplicationContext())
.connect(hostname).subscribe()));
} else if (!session.isTokenVerified()) {
statusTicker.updateStatus(StatusTicker.STATUS_TOKEN_LOGIN,
Snackbar.make(findViewById(getLayoutContainerForFragment()),
......@@ -219,11 +218,11 @@ public class MainActivity extends AbstractAuthedActivity {
unreadRoomSubscriptionObserver = null;
}
if (serverConfigId == null) {
if (hostname == null) {
return;
}
RealmHelper realmHelper = RealmStore.get(serverConfigId);
RealmHelper realmHelper = RealmStore.get(hostname);
if (realmHelper == null) {
return;
}
......@@ -253,7 +252,7 @@ public class MainActivity extends AbstractAuthedActivity {
private void updateSidebarMainFragment() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.sidebar_fragment_container, SidebarMainFragment.create(serverConfigId))
.replace(R.id.sidebar_fragment_container, SidebarMainFragment.create(hostname))
.commit();
}
......@@ -261,8 +260,8 @@ public class MainActivity extends AbstractAuthedActivity {
protected void onRoomIdUpdated() {
super.onRoomIdUpdated();
if (roomId != null && RoomFragment.canCreate(RealmStore.get(serverConfigId))) {
showFragment(RoomFragment.create(serverConfigId, roomId));
if (roomId != null && RoomFragment.canCreate(RealmStore.get(hostname))) {
showFragment(RoomFragment.create(hostname, roomId));
closeSidebarIfNeeded();
} else {
showFragment(new HomeFragment());
......
......@@ -121,10 +121,10 @@ public class DDPClientWrapper {
return ddpClient.ping(pingId)
.continueWithTask(task -> {
if (task.isFaulted()) {
RCLog.d("ping[%s] xxx failed xxx", pingId);
RCLog.d(task.getError(), "ping[%s] xxx failed xxx", pingId);
return Task.forError(task.getError());
} else {
RCLog.d("pong[%s] <");
RCLog.d("pong[%s] <", pingId);
return Task.forResult(null);
}
});
......
......@@ -12,8 +12,8 @@ import chat.rocket.android.realm_helper.RealmHelper;
* MethodCall for uploading file.
*/
public class FileUploadingHelper extends MethodCallHelper {
public FileUploadingHelper(Context context, String serverConfigId) {
super(context, serverConfigId);
public FileUploadingHelper(Context context, String hostname) {
super(context, hostname);
}
public FileUploadingHelper(RealmHelper realmHelper, DDPClientWrapper ddpClient) {
......
......@@ -39,11 +39,11 @@ public class MethodCallHelper {
protected final DDPClientWrapper ddpClient;
/**
* initialize with Context and ServerConfigId.
* initialize with Context and hostname.
*/
public MethodCallHelper(Context context, String serverConfigId) {
public MethodCallHelper(Context context, String hostname) {
this.context = context;
this.realmHelper = RealmStore.get(serverConfigId);
this.realmHelper = RealmStore.get(hostname);
ddpClient = null;
}
......
......@@ -10,8 +10,8 @@ import bolts.Task;
import chat.rocket.android.realm_helper.RealmHelper;
public class RaixPushHelper extends MethodCallHelper {
public RaixPushHelper(Context context, String serverConfigId) {
super(context, serverConfigId);
public RaixPushHelper(Context context, String hostname) {
super(context, hostname);
}
public RaixPushHelper(RealmHelper realmHelper,
......
package chat.rocket.android.fragment.server_config;
package chat.rocket.android.fragment.add_server;
import android.support.design.widget.Snackbar;
import android.widget.TextView;
import org.json.JSONObject;
import chat.rocket.android.BuildConfig;
import chat.rocket.android.LaunchUtil;
import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.rest.DefaultServerPolicyApi;
import chat.rocket.android.api.rest.ServerPolicyApi;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.fragment.AbstractFragment;
import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.helper.ServerPolicyApiValidationHelper;
import chat.rocket.android.helper.ServerPolicyHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.service.ConnectivityManagerApi;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
......@@ -24,12 +23,7 @@ import rx.schedulers.Schedulers;
/**
* Input server host.
*/
public class InputHostnameFragment extends AbstractServerConfigFragment {
RealmObjectObserver<ServerConfig> serverConfigObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.ID, serverConfigId))
.setOnUpdateListener(this::onRenderServerConfig);
public class InputHostnameFragment extends AbstractFragment {
Subscription serverPolicySubscription;
public InputHostnameFragment() {
......@@ -45,8 +39,6 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
setupVersionInfo();
rootView.findViewById(R.id.btn_connect).setOnClickListener(view -> handleConnect());
serverConfigObserver.sub();
}
private void setupVersionInfo() {
......@@ -67,9 +59,12 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
serverPolicySubscription.unsubscribe();
}
rootView.findViewById(R.id.btn_connect).setEnabled(false);
serverPolicySubscription = ServerPolicyHelper.isApiVersionValid(validationHelper)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnTerminate(() -> rootView.findViewById(R.id.btn_connect).setEnabled(true))
.subscribe(
serverValidation -> {
if (serverValidation.isValid()) {
......@@ -85,7 +80,6 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
@Override
public void onDestroyView() {
serverConfigObserver.unsub();
if (serverPolicySubscription != null) {
serverPolicySubscription.unsubscribe();
}
......@@ -100,36 +94,19 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
private void onServerValid(final String hostname, boolean usesSecureConnection) {
RocketChatCache.get(getContext()).edit()
.putString(RocketChatCache.KEY_SELECTED_SERVER_CONFIG_ID, serverConfigId)
.putString(RocketChatCache.KEY_SELECTED_SERVER_HOSTNAME, hostname)
.apply();
RealmStore.getDefault().executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class,
new JSONObject().put(ServerConfig.ID, serverConfigId)
.put(ServerConfig.HOSTNAME, hostname)
.put(ServerConfig.ERROR, JSONObject.NULL)
.put(ServerConfig.SESSION, JSONObject.NULL)
.put(ServerConfig.SECURE_CONNECTION, usesSecureConnection)
.put(ServerConfig.STATE, ServerConfig.STATE_READY)))
.continueWith(new LogcatIfError());
ConnectivityManagerApi connectivityManager =
ConnectivityManager.getInstance(getContext().getApplicationContext());
connectivityManager.addOrUpdateServer(hostname, hostname, !usesSecureConnection);
connectivityManager.keepAliveServer();
LaunchUtil.showMainActivity(getContext());
getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
private void showError(String errString) {
Snackbar.make(rootView, errString, Snackbar.LENGTH_LONG).show();
}
private void onRenderServerConfig(ServerConfig config) {
if (config == null) {
return;
}
final TextView editor = (TextView) rootView.findViewById(R.id.editor_hostname);
if (!TextUtils.isEmpty(config.getHostname())) {
editor.setText(config.getHostname());
}
if (!TextUtils.isEmpty(config.getError())) {
showError(config.getError());
}
}
}
......@@ -34,9 +34,9 @@ import chat.rocket.android.helper.OnBackPressListener;
import chat.rocket.android.helper.RecyclerViewAutoScrollManager;
import chat.rocket.android.helper.RecyclerViewScrolledToBottomListener;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.layouthelper.chatroom.AbstractNewMessageIndicatorManager;
import chat.rocket.android.layouthelper.chatroom.MessageFormManager;
import chat.rocket.android.layouthelper.chatroom.MessageListAdapter;
import chat.rocket.android.layouthelper.chatroom.AbstractNewMessageIndicatorManager;
import chat.rocket.android.layouthelper.chatroom.PairedMessage;
import chat.rocket.android.layouthelper.extra_action.AbstractExtraActionItem;
import chat.rocket.android.layouthelper.extra_action.MessageExtraActionBehavior;
......@@ -45,7 +45,6 @@ import chat.rocket.android.layouthelper.extra_action.upload.AudioUploadActionIte
import chat.rocket.android.layouthelper.extra_action.upload.ImageUploadActionItem;
import chat.rocket.android.layouthelper.extra_action.upload.VideoUploadActionItem;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.model.ddp.RoomSubscription;
......@@ -56,7 +55,7 @@ import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmModelListAdapter;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.RocketChatService;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.widget.internal.ExtraActionPickerDialogFragment;
import chat.rocket.android.widget.message.MessageFormLayout;
import permissions.dispatcher.NeedsPermission;
......@@ -72,11 +71,10 @@ public class RoomFragment extends AbstractChatRoomFragment
private static final int DIALOG_ID = 1;
private String serverConfigId;
private String hostname;
private RealmHelper realmHelper;
private String roomId;
private RealmObjectObserver<RoomSubscription> roomObserver;
private String hostname;
private String userId;
private String token;
private LoadMoreScrollListener scrollListener;
......@@ -103,9 +101,9 @@ public class RoomFragment extends AbstractChatRoomFragment
/**
* create fragment with roomId.
*/
public static RoomFragment create(String serverConfigId, String roomId) {
public static RoomFragment create(String hostname, String roomId) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
args.putString("roomId", roomId);
RoomFragment fragment = new RoomFragment();
fragment.setArguments(args);
......@@ -117,14 +115,9 @@ public class RoomFragment extends AbstractChatRoomFragment
super.onCreate(savedInstanceState);
Bundle args = getArguments();
serverConfigId = args.getString("serverConfigId");
realmHelper = RealmStore.get(serverConfigId);
hostname = args.getString("hostname");
realmHelper = RealmStore.get(hostname);
roomId = args.getString("roomId");
hostname = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class)
.equalTo(ServerConfig.ID, serverConfigId)
.isNotNull(ServerConfig.HOSTNAME)
.findFirst()).getHostname();
userId = realmHelper.executeTransactionForRead(realm ->
User.queryCurrentUser(realm).findFirst()).getId();
token = realmHelper.executeTransactionForRead(realm ->
......@@ -281,7 +274,7 @@ public class RoomFragment extends AbstractChatRoomFragment
private void setupSideMenu() {
View sideMenu = rootView.findViewById(R.id.room_side_menu);
sideMenu.findViewById(R.id.btn_users).setOnClickListener(view -> {
UsersOfRoomDialogFragment.create(serverConfigId, roomId, hostname)
UsersOfRoomDialogFragment.create(roomId, hostname)
.show(getFragmentManager(), UsersOfRoomDialogFragment.class.getSimpleName());
closeSideMenuIfNeeded();
});
......@@ -347,7 +340,7 @@ public class RoomFragment extends AbstractChatRoomFragment
String uplId = new FileUploadHelper(getContext(), realmHelper)
.requestUploading(roomId, data.getData());
if (!TextUtils.isEmpty(uplId)) {
FileUploadProgressDialogFragment.create(serverConfigId, roomId, uplId)
FileUploadProgressDialogFragment.create(hostname, roomId, uplId)
.show(getFragmentManager(), FileUploadProgressDialogFragment.class.getSimpleName());
} else {
// show error.
......@@ -406,7 +399,8 @@ public class RoomFragment extends AbstractChatRoomFragment
.put(LoadMessageProcedure.RESET, true));
return null;
}).onSuccessTask(task -> {
RocketChatService.keepAlive(getContext());
ConnectivityManager.getInstance(getContext().getApplicationContext())
.keepAliveServer();
return task;
}).continueWith(new LogcatIfError());
}
......@@ -427,7 +421,8 @@ public class RoomFragment extends AbstractChatRoomFragment
}
return null;
}).onSuccessTask(task -> {
RocketChatService.keepAlive(getContext());
ConnectivityManager.getInstance(getContext().getApplicationContext())
.keepAliveServer();
return task;
}).continueWith(new LogcatIfError());
}
......@@ -436,7 +431,7 @@ public class RoomFragment extends AbstractChatRoomFragment
RoomSubscription room = realmHelper.executeTransactionForRead(realm ->
realm.where(RoomSubscription.class).equalTo(RoomSubscription.ROOM_ID, roomId).findFirst());
if (room != null && room.isAlert()) {
new MethodCallHelper(getContext(), serverConfigId).readMessages(roomId)
new MethodCallHelper(getContext(), hostname).readMessages(roomId)
.continueWith(new LogcatIfError());
}
}
......
......@@ -31,8 +31,8 @@ abstract class AbstractChatRoomDialogFragment extends BottomSheetDialogFragment
}
protected void handleArgs(@NonNull Bundle args) {
String serverConfigId = args.getString("serverConfigId");
realmHelper = RealmStore.get(serverConfigId);
String hostname = args.getString("hostname");
realmHelper = RealmStore.get(hostname);
roomId = args.getString("roomId");
}
......
......@@ -25,10 +25,10 @@ public class FileUploadProgressDialogFragment extends AbstractChatRoomDialogFrag
public FileUploadProgressDialogFragment() {
}
public static FileUploadProgressDialogFragment create(String serverConfigId,
public static FileUploadProgressDialogFragment create(String hostname,
String roomId, String uplId) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
args.putString("roomId", roomId);
args.putString("uplId", uplId);
......
......@@ -20,7 +20,7 @@ import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.internal.GetUsersOfRoomsProcedure;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.service.RocketChatService;
import chat.rocket.android.service.ConnectivityManager;
/**
* Dialog to show members in a room.
......@@ -37,12 +37,10 @@ public class UsersOfRoomDialogFragment extends AbstractChatRoomDialogFragment {
/**
* create UsersOfRoomDialogFragment with required parameters.
*/
public static UsersOfRoomDialogFragment create(String serverConfigId,
String roomId, String hostname) {
public static UsersOfRoomDialogFragment create(String roomId, String hostname) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("roomId", roomId);
args.putString("hostname", hostname);
args.putString("roomId", roomId);
UsersOfRoomDialogFragment fragment = new UsersOfRoomDialogFragment();
fragment.setArguments(args);
......@@ -91,7 +89,8 @@ public class UsersOfRoomDialogFragment extends AbstractChatRoomDialogFragment {
.put("showAll", true));
return null;
}).onSuccessTask(task -> {
RocketChatService.keepAlive(getContext());
ConnectivityManager.getInstance(getContext().getApplicationContext())
.keepAliveServer();
return task;
}).continueWith(new LogcatIfError());
}
......
......@@ -14,13 +14,11 @@ import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.fragment.AbstractWebViewFragment;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import chat.rocket.android.realm_helper.RealmStore;
public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
protected String serverConfigId;
protected String hostname;
private String url;
private boolean resultOK;
......@@ -31,7 +29,7 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
private boolean hasValidArgs(Bundle args) {
return args != null
&& args.containsKey("serverConfigId");
&& args.containsKey("hostname");
}
protected final String getStateString() {
......@@ -52,22 +50,19 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
Bundle args = getArguments();
if (!hasValidArgs(args)) {
throw new IllegalArgumentException(
"serverConfigId required");
"hostname required");
}
serverConfigId = args.getString("serverConfigId");
ServerConfig serverConfig = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.ID, serverConfigId).findFirst());
hostname = args.getString("hostname");
MeteorLoginServiceConfiguration oauthConfig =
RealmStore.get(serverConfigId).executeTransactionForRead(realm ->
RealmStore.get(hostname).executeTransactionForRead(realm ->
realm.where(MeteorLoginServiceConfiguration.class)
.equalTo(MeteorLoginServiceConfiguration.SERVICE, getOAuthServiceName())
.findFirst());
if (serverConfig == null || oauthConfig == null) {
if (oauthConfig == null) {
throw new IllegalArgumentException(
"Invalid serverConfigId given,");
"Invalid hostname given,");
}
hostname = serverConfig.getHostname();
url = generateURL(oauthConfig);
}
......@@ -114,7 +109,7 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
}
private void handleOAuthCallback(final String credentialToken, final String credentialSecret) {
new MethodCallHelper(getContext(), serverConfigId)
new MethodCallHelper(getContext(), hostname)
.loginWithOAuth(credentialToken, credentialSecret)
.continueWith(new LogcatIfError());
}
......
......@@ -9,7 +9,7 @@ import chat.rocket.android.fragment.AbstractFragment;
import chat.rocket.android.helper.TextUtils;
abstract class AbstractServerConfigFragment extends AbstractFragment {
protected String serverConfigId;
protected String hostname;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
......@@ -21,8 +21,8 @@ abstract class AbstractServerConfigFragment extends AbstractFragment {
return;
}
serverConfigId = args.getString("serverConfigId");
if (TextUtils.isEmpty(serverConfigId)) {
hostname = args.getString("hostname");
if (TextUtils.isEmpty(hostname)) {
finish();
return;
}
......
......@@ -32,7 +32,7 @@ public class LoginFragment extends AbstractServerConfigFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
authProvidersObserver = RealmStore.get(serverConfigId)
authProvidersObserver = RealmStore.get(hostname)
.createListObserver(realm -> realm.where(MeteorLoginServiceConfiguration.class).findAll())
.setOnUpdateListener(this::onRenderAuthProviders);
}
......@@ -52,7 +52,7 @@ public class LoginFragment extends AbstractServerConfigFragment {
view.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
new MethodCallHelper(getContext(), serverConfigId)
new MethodCallHelper(getContext(), hostname)
.loginWithEmail(username.toString(), passwd.toString())
.continueWith(task -> {
if (task.isFaulted()) {
......@@ -65,7 +65,7 @@ public class LoginFragment extends AbstractServerConfigFragment {
});
final View btnUserRegistration = rootView.findViewById(R.id.btn_user_registration);
btnUserRegistration.setOnClickListener(view -> UserRegistrationDialogFragment.create(serverConfigId,
btnUserRegistration.setOnClickListener(view -> UserRegistrationDialogFragment.create(hostname,
txtUsername.getText().toString(), txtPasswd.getText().toString())
.show(getFragmentManager(), UserRegistrationDialogFragment.class.getSimpleName()));
}
......@@ -96,7 +96,7 @@ public class LoginFragment extends AbstractServerConfigFragment {
}
if (fragment != null) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
fragment.setArguments(args);
showFragmentWithBackStack(fragment);
}
......
package chat.rocket.android.fragment.server_config;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
/**
* Login screen.
*/
public class RetryConnectFragment extends AbstractServerConfigFragment {
private RealmObjectObserver<ServerConfig> serverConfigObserver;
@Override
protected int getLayout() {
return R.layout.fragment_retry_login;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serverConfigObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.ID, serverConfigId))
.setOnUpdateListener(this::onRenderServerConfig);
}
@Override
protected void onSetupView() {
rootView.findViewById(R.id.waiting).setVisibility(View.GONE);
final View btnRetry = rootView.findViewById(R.id.btn_retry_login);
btnRetry.setOnClickListener(view -> {
RealmStore.getDefault()
.executeTransaction(realm -> {
ServerConfig config = realm.where(ServerConfig.class)
.equalTo(ServerConfig.ID, serverConfigId).findFirst();
if (config != null && config.getState() == ServerConfig.STATE_CONNECTION_ERROR) {
config.setState(ServerConfig.STATE_READY);
}
return null;
}).continueWith(new LogcatIfError());
});
}
private void onRenderServerConfig(ServerConfig config) {
if (config == null) {
return;
}
final String error = config.getError();
final TextView txtError = (TextView) rootView.findViewById(R.id.txt_error_description);
if (!TextUtils.isEmpty(error)) {
txtError.setText(error);
}
final int state = config.getState();
if (state == ServerConfig.STATE_CONNECTED) {
finish();
}
rootView.findViewById(R.id.btn_retry_login)
.setEnabled(state == ServerConfig.STATE_CONNECTION_ERROR);
}
@Override
public void onResume() {
super.onResume();
serverConfigObserver.sub();
}
@Override
public void onPause() {
serverConfigObserver.unsub();
super.onPause();
}
}
......@@ -26,7 +26,7 @@ public class RetryLoginFragment extends AbstractServerConfigFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessionObserver = RealmStore.get(serverConfigId)
sessionObserver = RealmStore.get(hostname)
.createObjectObserver(Session::queryDefaultSession)
.setOnUpdateListener(this::onRenderServerConfigSession);
}
......@@ -49,7 +49,7 @@ public class RetryLoginFragment extends AbstractServerConfigFragment {
view.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
new MethodCallHelper(getContext(), serverConfigId).loginWithToken(token)
new MethodCallHelper(getContext(), hostname).loginWithToken(token)
.continueWith(task -> {
if (task.isFaulted()) {
view.setEnabled(true);
......
......@@ -20,7 +20,7 @@ import chat.rocket.android.helper.TextUtils;
* Dialog for user registration.
*/
public class UserRegistrationDialogFragment extends DialogFragment {
private String serverConfigId;
private String hostname;
private String username;
private String email;
private String password;
......@@ -32,23 +32,23 @@ public class UserRegistrationDialogFragment extends DialogFragment {
/**
* create UserRegistrationDialogFragment with auto-detect email/username.
*/
public static UserRegistrationDialogFragment create(String serverConfigId,
public static UserRegistrationDialogFragment create(String hostname,
String usernameOrEmail, String password) {
if (Patterns.EMAIL_ADDRESS.matcher(usernameOrEmail).matches()) {
return create(serverConfigId, null, usernameOrEmail, password);
return create(hostname, null, usernameOrEmail, password);
} else {
return create(serverConfigId, usernameOrEmail, null, password);
return create(hostname, usernameOrEmail, null, password);
}
}
/**
* create UserRegistrationDialogFragment.
*/
public static UserRegistrationDialogFragment create(String serverConfigId,
public static UserRegistrationDialogFragment create(String hostname,
String username, String email,
String password) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
if (!TextUtils.isEmpty(username)) {
args.putString("username", username);
}
......@@ -69,7 +69,7 @@ public class UserRegistrationDialogFragment extends DialogFragment {
Bundle args = getArguments();
if (args != null) {
serverConfigId = args.getString("serverConfigId");
hostname = args.getString("hostname");
username = args.getString("username");
email = args.getString("email");
password = args.getString("password");
......@@ -113,7 +113,7 @@ public class UserRegistrationDialogFragment extends DialogFragment {
email = txtEmail.getText().toString();
password = txtPasswd.getText().toString();
MethodCallHelper methodCallHelper = new MethodCallHelper(getContext(), serverConfigId);
MethodCallHelper methodCallHelper = new MethodCallHelper(getContext(), hostname);
methodCallHelper.registerUser(username, email, password, password)
.onSuccessTask(task -> methodCallHelper.loginWithEmail(email, password))
.onSuccessTask(task -> methodCallHelper.setUsername(username)) //TODO: should prompt!
......
......@@ -7,6 +7,8 @@ import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.jakewharton.rxbinding.view.RxView;
import com.jakewharton.rxbinding.widget.RxCompoundButton;
import chat.rocket.android.BuildConfig;
import chat.rocket.android.R;
......@@ -14,12 +16,11 @@ import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.fragment.AbstractFragment;
import chat.rocket.android.fragment.sidebar.dialog.AbstractAddRoomDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddDirectMessageDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddChannelDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddDirectMessageDialogFragment;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.layouthelper.chatroom.RoomListManager;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.realm_helper.RealmHelper;
......@@ -28,14 +29,10 @@ import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.renderer.UserRenderer;
import com.jakewharton.rxbinding.view.RxView;
import com.jakewharton.rxbinding.widget.RxCompoundButton;
public class SidebarMainFragment extends AbstractFragment {
private String serverConfigId;
private RoomListManager roomListManager;
private String hostname;
private RoomListManager roomListManager;
private RealmListObserver<RoomSubscription> roomsObserver;
private RealmObjectObserver<User> currentUserObserver;
private MethodCallHelper methodCallHelper;
......@@ -44,11 +41,11 @@ public class SidebarMainFragment extends AbstractFragment {
}
/**
* create SidebarMainFragment with serverConfigId.
* create SidebarMainFragment with hostname.
*/
public static SidebarMainFragment create(String serverConfigId) {
public static SidebarMainFragment create(String hostname) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
SidebarMainFragment fragment = new SidebarMainFragment();
fragment.setArguments(args);
......@@ -60,15 +57,9 @@ public class SidebarMainFragment extends AbstractFragment {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
serverConfigId = args == null ? null : args.getString("serverConfigId");
if (!TextUtils.isEmpty(serverConfigId)) {
ServerConfig config = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.ID, serverConfigId).findFirst());
if (config != null) {
hostname = config.getHostname();
}
RealmHelper realmHelper = RealmStore.get(serverConfigId);
hostname = args == null ? null : args.getString("hostname");
if (!TextUtils.isEmpty(hostname)) {
RealmHelper realmHelper = RealmStore.get(hostname);
if (realmHelper != null) {
roomsObserver = realmHelper
.createListObserver(
......@@ -80,14 +71,14 @@ public class SidebarMainFragment extends AbstractFragment {
.createObjectObserver(User::queryCurrentUser)
.setOnUpdateListener(this::onCurrentUser);
methodCallHelper = new MethodCallHelper(getContext(), serverConfigId);
methodCallHelper = new MethodCallHelper(getContext(), hostname);
}
}
}
@Override
protected int getLayout() {
if (serverConfigId == null) {
if (hostname == null) {
return R.layout.simple_screen;
} else {
return R.layout.fragment_sidebar_main;
......@@ -96,7 +87,7 @@ public class SidebarMainFragment extends AbstractFragment {
@Override
protected void onSetupView() {
if (serverConfigId == null) {
if (hostname == null) {
return;
}
......@@ -203,7 +194,6 @@ public class SidebarMainFragment extends AbstractFragment {
private void showAddRoomDialog(DialogFragment dialog) {
Bundle args = new Bundle();
args.putString("serverConfigId", serverConfigId);
args.putString("hostname", hostname);
dialog.setArguments(args);
dialog.show(getFragmentManager(), AbstractAddRoomDialogFragment.class.getSimpleName());
......
......@@ -38,10 +38,9 @@ public abstract class AbstractAddRoomDialogFragment extends RxAppCompatDialogFra
}
protected void handleArgs(@NonNull Bundle args) {
String serverConfigId = args.getString("serverConfigId");
realmHelper = RealmStore.get(serverConfigId);
methodCall = new MethodCallHelper(getContext(), serverConfigId);
hostname = args.getString("hostname");
realmHelper = RealmStore.get(hostname);
methodCall = new MethodCallHelper(getContext(), hostname);
}
@Override
......
package chat.rocket.android.helper;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.Single;
import rx.functions.Func0;
import rx.functions.Func1;
/**
* Rx operator and so on.
*/
public class RxHelper {
public static Func1<Observable<? extends Throwable>, Observable<?>> exponentialBackoff(
int maxRetryCount, long base, TimeUnit unit) {
return errors -> errors
.zipWith(Observable.range(0, maxRetryCount), (error, retryCount) -> retryCount)
.flatMap(retryCount -> Observable.timer(base * (long) Math.pow(2, retryCount), unit));
}
public static <T> Single<T> lazy(Func0<Single<T>> func) {
return Single.just(true).flatMap(_junk -> func.call());
}
}
......@@ -13,10 +13,10 @@ public class ServerPolicyApiValidationHelper {
this.serverPolicyApi = serverPolicyApi;
}
public Observable<ServerPolicyHelper.ServerInfo> getApiVersion() {
public Observable<ServerPolicyHelper.ServerInfoResponse> getApiVersion() {
return serverPolicyApi.getApiInfoSecurely()
.onErrorResumeNext(serverPolicyApi.getApiInfoInsecurely())
.map(response -> new ServerPolicyHelper.ServerInfo(
.map(response -> new ServerPolicyHelper.ServerInfoResponse(
response.getProtocol().equals(ServerPolicyApi.SECURE_PROTOCOL),
response.getData()
));
......
......@@ -72,11 +72,11 @@ public class ServerPolicyHelper {
return versionParts.length >= 3 && Integer.parseInt(versionParts[1]) >= 49;
}
public static class ServerInfo {
public static class ServerInfoResponse {
private final boolean secureConnection;
private final JSONObject apiInfo;
public ServerInfo(boolean secureConnection, JSONObject apiInfo) {
public ServerInfoResponse(boolean secureConnection, JSONObject apiInfo) {
this.secureConnection = secureConnection;
this.apiInfo = apiInfo;
}
......
package chat.rocket.android.model;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Server configuration.
*/
@Deprecated
public class ServerConfig extends RealmObject {
@SuppressWarnings({"PMD.ShortVariable"})
public static final String ID = "serverConfigId";
public static final String HOSTNAME = "hostname";
public static final String STATE = "state";
public static final String SESSION = "session";
public static final String SECURE_CONNECTION = "secureConnection";
public static final String ERROR = "error";
public static final int STATE_READY = 0;
public static final int STATE_CONNECTING = 1;
public static final int STATE_CONNECTED = 2;
public static final int STATE_CONNECTION_ERROR = 3;
@PrimaryKey private String serverConfigId;
private String hostname;
private int state;
private String session;
private boolean secureConnection;
private String error;
public String getServerConfigId() {
return serverConfigId;
}
public void setServerConfigId(String serverConfigId) {
this.serverConfigId = serverConfigId;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
public boolean usesSecureConnection() {
return secureConnection;
}
public void setSecureConnection(boolean usesSecureConnection) {
this.secureConnection = usesSecureConnection;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
}
......@@ -16,7 +16,7 @@ import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.service.RocketChatService;
import chat.rocket.android.service.ConnectivityManager;
public class MethodCall extends RealmObject {
......@@ -89,7 +89,8 @@ public class MethodCall extends RealmObject {
REF_MAP.put(newId, observer);
if (context != null) {
RocketChatService.keepAlive(context);
ConnectivityManager.getInstance(context.getApplicationContext())
.keepAliveServer();
}
}
return null;
......
......@@ -70,6 +70,6 @@ public interface PushConstants {
String FORCE_START = "force-start";
// RC specific constants
String SERVER_CONFIG_ID = "serverConfigId";
String HOSTNAME = "hostname";
String ROOM_ID = "roomId";
}
\ No newline at end of file
......@@ -20,7 +20,6 @@ import android.support.v4.util.SparseArrayCompat;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
......@@ -32,7 +31,6 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import chat.rocket.android.activity.MainActivity;
import chat.rocket.android.push.interactors.PushInteractor;
public class PushNotificationHandler implements PushConstants {
......@@ -64,8 +62,7 @@ public class PushNotificationHandler implements PushConstants {
return messageMap.get(notId);
}
public void showNotificationIfPossible(Context context, PushInteractor pushInteractor,
Bundle extras) {
public void showNotificationIfPossible(Context context, Bundle extras) {
// Send a notification if there is a message or title, otherwise just send data
String message = extras.getString(MESSAGE);
......@@ -87,26 +84,21 @@ public class PushNotificationHandler implements PushConstants {
extras.putString(TITLE, getAppName(context));
}
createNotification(context, pushInteractor, extras);
createNotification(context, extras);
}
}
public void createNotification(Context context, PushInteractor pushInteractor, Bundle extras) {
public void createNotification(Context context, Bundle extras) {
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String appName = getAppName(context);
String packageName = context.getPackageName();
Resources resources = context.getResources();
String serverUrl = getServerUrl(extras);
String hostname = getHostname(extras);
String roomId = getRoomId(extras);
if (serverUrl == null || roomId == null) {
return;
}
String serverConfigId = pushInteractor.getServerConfigId(serverUrl);
if (serverConfigId == null) {
if (hostname == null || roomId == null) {
return;
}
......@@ -114,7 +106,7 @@ public class PushNotificationHandler implements PushConstants {
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra(PUSH_BUNDLE, extras);
notificationIntent.putExtra(SERVER_CONFIG_ID, serverConfigId);
notificationIntent.putExtra(HOSTNAME, hostname);
notificationIntent.putExtra(ROOM_ID, roomId);
notificationIntent.putExtra(NOT_ID, notId);
......@@ -634,7 +626,7 @@ public class PushNotificationHandler implements PushConstants {
return count;
}
private String getServerUrl(Bundle extras) {
private String getHostname(Bundle extras) {
try {
JSONObject jsonObject = new JSONObject(extras.getString("ejson", "[]"));
if (!jsonObject.has("host")) {
......
......@@ -15,8 +15,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import chat.rocket.android.push.PushConstants;
import chat.rocket.android.push.PushNotificationHandler;
import chat.rocket.android.push.interactors.DefaultPushInteractor;
import chat.rocket.android.push.interactors.PushInteractor;
@SuppressLint("NewApi")
public class GCMIntentService extends GcmListenerService implements PushConstants {
......@@ -33,13 +31,11 @@ public class GCMIntentService extends GcmListenerService implements PushConstant
Context applicationContext = getApplicationContext();
PushInteractor pushInteractor = new DefaultPushInteractor();
extras = normalizeExtras(applicationContext, extras);
PushNotificationHandler pushNotificationHandler = new PushNotificationHandler();
pushNotificationHandler.showNotificationIfPossible(applicationContext, pushInteractor, extras);
pushNotificationHandler.showNotificationIfPossible(applicationContext, extras);
}
/*
......
......@@ -4,24 +4,21 @@ import com.google.android.gms.iid.InstanceIDListenerService;
import java.util.List;
import chat.rocket.android.helper.GcmPushSettingHelper;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.PublicSetting;
import chat.rocket.android.model.internal.GcmPushRegistration;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.service.ServerInfo;
public class GcmInstanceIDListenerService extends InstanceIDListenerService {
@Override
public void onTokenRefresh() {
List<ServerConfig> serverConfigs = RealmStore.getDefault()
.executeTransactionForReadResults(realm ->
realm.where(ServerConfig.class)
.isNotNull(ServerConfig.ID)
.isNotNull(ServerConfig.HOSTNAME)
.findAll());
for (ServerConfig serverConfig : serverConfigs) {
RealmHelper realmHelper = RealmStore.get(serverConfig.getServerConfigId());
List<ServerInfo> serverInfoList = ConnectivityManager.getInstance(getApplicationContext())
.getServerList();
for (ServerInfo serverInfo : serverInfoList) {
RealmHelper realmHelper = RealmStore.get(serverInfo.hostname);
if (realmHelper != null) {
updateGcmToken(realmHelper);
}
......
package chat.rocket.android.push.interactors;
import chat.rocket.android.helper.ServerPolicyHelper;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmStore;
public class DefaultPushInteractor implements PushInteractor {
@Override
public String getServerConfigId(String hostname) {
final ServerConfig serverConfig = RealmStore.getDefault()
.executeTransactionForRead(
realm -> realm.where(ServerConfig.class)
.equalTo(ServerConfig.HOSTNAME, ServerPolicyHelper.enforceHostname(hostname))
.findFirst());
return serverConfig != null ? serverConfig.getServerConfigId() : "";
}
}
package chat.rocket.android.push.interactors;
public interface PushInteractor {
String getServerConfigId(String hostname);
}
......@@ -3,8 +3,8 @@ package chat.rocket.android.service;
import android.support.annotation.Nullable;
import java.util.List;
import rx.Completable;
import rx.Observable;
import rx.Single;
/**
* interfaces used for Activity/Fragment and other UI-related logic.
......@@ -12,11 +12,11 @@ import rx.Observable;
public interface ConnectivityManagerApi {
void keepAliveServer();
void addOrUpdateServer(String hostname, @Nullable String name);
void addOrUpdateServer(String hostname, @Nullable String name, boolean insecure);
void removeServer(String hostname);
Completable connect(String hostname);
Single<Boolean> connect(String hostname);
List<ServerInfo> getServerList();
......
......@@ -10,15 +10,18 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import rx.Completable;
import java.util.concurrent.TimeUnit;
import chat.rocket.android.helper.RxHelper;
import chat.rocket.android.log.RCLog;
import hugo.weaving.DebugLog;
import rx.Observable;
import rx.Single;
import rx.subjects.PublishSubject;
/**
* Connectivity management implementation.
*/
/*package*/ class ConnectivityManagerImpl implements ConnectivityManagerApi, ConnectivityManagerInternal {
private final HashMap<String, Integer> serverConnectivityList = new HashMap<>();
private final PublishSubject<ServerConnectivity> connectivitySubject = PublishSubject.create();
private Context appContext;
......@@ -60,29 +63,35 @@ import rx.subjects.PublishSubject;
@Override
public void ensureConnections() {
for (String hostname : serverConnectivityList.keySet()) {
connectToServer(hostname); //force connect.
connectToServer(hostname) //force connect.
//.doOnError(RCLog::e)
.retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS))
.subscribe(_val -> { }, RCLog::e);
}
}
@Override
public void addOrUpdateServer(String hostname, @Nullable String name) {
public void addOrUpdateServer(String hostname, @Nullable String name, boolean insecure) {
ServerInfoImpl.addOrUpdate(hostname, name);
ServerInfoImpl.setInsecure(hostname, insecure);
if (!serverConnectivityList.containsKey(hostname)) {
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTED);
}
connectToServerIfNeeded(hostname);
connectToServerIfNeeded(hostname)
.subscribe(_val -> { }, RCLog::e);
}
@Override
public void removeServer(String hostname) {
ServerInfoImpl.remove(hostname);
if (serverConnectivityList.containsKey(hostname)) {
disconnectFromServerIfNeeded(hostname);
disconnectFromServerIfNeeded(hostname)
.subscribe(_val -> { }, RCLog::e);
}
}
@Override
public Completable connect(String hostname) {
public Single<Boolean> connect(String hostname) {
return connectToServerIfNeeded(hostname);
}
......@@ -104,6 +113,7 @@ import rx.subjects.PublishSubject;
return list;
}
@DebugLog
@Override
public void notifyConnectionEstablished(String hostname, String session) {
ServerInfoImpl.updateSession(hostname, session);
......@@ -112,6 +122,7 @@ import rx.subjects.PublishSubject;
new ServerConnectivity(hostname, ServerConnectivity.STATE_CONNECTED));
}
@DebugLog
@Override
public void notifyConnectionLost(String hostname, int reason) {
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTED);
......@@ -124,80 +135,96 @@ import rx.subjects.PublishSubject;
return Observable.concat(Observable.from(getCurrentConnectivityList()), connectivitySubject);
}
private Completable connectToServerIfNeeded(String hostname) {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_CONNECTED) {
return Completable.complete();
}
private Single<Boolean> connectToServerIfNeeded(String hostname) {
return RxHelper.lazy(() -> {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_CONNECTED) {
return Single.just(true);
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname).andThen(connectToServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname)
.flatMap(_val -> connectToServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname);
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname);
}
return connectToServer(hostname).retry(2);
return connectToServer(hostname)
//.doOnError(RCLog::e)
.retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS));
});
}
private Completable disconnectFromServerIfNeeded(String hostname) {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_DISCONNECTED) {
return Completable.complete();
}
private Single<Boolean> disconnectFromServerIfNeeded(String hostname) {
return RxHelper.lazy(() -> {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_DISCONNECTED) {
return Single.just(true);
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname).andThen(disconnectFromServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname)
.flatMap(_val -> disconnectFromServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname);
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname);
}
return disconnectFromServer(hostname).retry(2);
return disconnectFromServer(hostname)
//.doOnError(RCLog::e)
.retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS));
});
}
private Completable waitForConnected(String hostname) {
private Single<Boolean> waitForConnected(String hostname) {
return connectivitySubject
.filter(serverConnectivity -> (hostname.equals(serverConnectivity.hostname)
&& serverConnectivity.state == ServerConnectivity.STATE_CONNECTED))
.first()
.toCompletable();
.map(serverConnectivity -> true)
.toSingle();
}
private Completable waitForDisconnected(String hostname) {
private Single<Boolean> waitForDisconnected(String hostname) {
return connectivitySubject
.filter(serverConnectivity -> (hostname.equals(serverConnectivity.hostname)
&& serverConnectivity.state == ServerConnectivity.STATE_DISCONNECTED))
.first()
.toCompletable();
}
private Completable connectToServer(String hostname) {
if (!serverConnectivityList.containsKey(hostname)) {
throw new IllegalArgumentException("hostname not found");
}
serverConnectivityList.put(hostname, ServerConnectivity.STATE_CONNECTING);
if (serviceInterface != null) {
return serviceInterface.ensureConnectionToServer(hostname);
} else {
return Completable.error(new IllegalStateException("not prepared"));
}
}
private Completable disconnectFromServer(String hostname) {
if (!serverConnectivityList.containsKey(hostname)) {
throw new IllegalArgumentException("hostname not found");
}
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTING);
if (serviceInterface != null) {
return serviceInterface.disconnectFromServer(hostname);
} else {
return Completable.error(new IllegalStateException("not prepared"));
}
.map(serverConnectivity -> true)
.toSingle();
}
private Single<Boolean> connectToServer(String hostname) {
return RxHelper.lazy(() -> {
if (!serverConnectivityList.containsKey(hostname)) {
return Single.error(new IllegalArgumentException("hostname not found"));
}
serverConnectivityList.put(hostname, ServerConnectivity.STATE_CONNECTING);
if (serviceInterface != null) {
return serviceInterface.ensureConnectionToServer(hostname);
} else {
return Single.error(new IllegalStateException("not prepared"));
}
});
}
private Single<Boolean> disconnectFromServer(String hostname) {
return RxHelper.lazy(() -> {
if (!serverConnectivityList.containsKey(hostname)) {
return Single.error(new IllegalArgumentException("hostname not found"));
}
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTING);
if (serviceInterface != null) {
return serviceInterface.disconnectFromServer(hostname);
} else {
return Single.error(new IllegalStateException("not prepared"));
}
});
}
}
package chat.rocket.android.service;
import rx.Completable;
import rx.Single;
public interface ConnectivityServiceInterface {
Completable ensureConnectionToServer(String hostname);
Single<Boolean> ensureConnectionToServer(String hostname);
Completable disconnectFromServer(String hostname);
Single<Boolean> disconnectFromServer(String hostname);
}
......@@ -10,7 +10,9 @@ import android.support.annotation.Nullable;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import rx.Completable;
import chat.rocket.android.helper.RxHelper;
import hugo.weaving.DebugLog;
import rx.Observable;
import rx.Single;
/**
......@@ -32,7 +34,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
/**
* ensure RocketChatService alive.
*/
public static void keepAlive(Context context) {
/*package*/ static void keepAlive(Context context) {
context.startService(new Intent(context, RocketChatService.class));
}
......@@ -61,43 +63,50 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
}
@Override
public Completable ensureConnectionToServer(String hostname) { //called via binder.
public Single<Boolean> ensureConnectionToServer(String hostname) { //called via binder.
return getOrCreateWebSocketThread(hostname)
.doOnError(err -> {
webSocketThreads.remove(hostname);
connectivityManager.notifyConnectionLost(hostname, ConnectivityManagerInternal.REASON_NETWORK_ERROR);
})
.flatMapCompletable(webSocketThreads -> webSocketThreads.keepAlive());
.flatMap(webSocketThreads -> webSocketThreads.keepAlive());
}
@Override
public Completable disconnectFromServer(String hostname) { //called via binder.
if (!webSocketThreads.containsKey(hostname)) {
return Completable.complete();
}
RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
if (thread != null) {
return thread.terminate();
} else {
return Completable.timer(1, TimeUnit.SECONDS).andThen(disconnectFromServer(hostname));
}
}
public Single<Boolean> disconnectFromServer(String hostname) { //called via binder.
return RxHelper.lazy(() -> {
if (!webSocketThreads.containsKey(hostname)) {
return Single.just(true);
}
private Single<RocketChatWebSocketThread> getOrCreateWebSocketThread(String hostname) {
if (webSocketThreads.containsKey(hostname)) {
RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
if (thread != null) {
return Single.just(thread);
return thread.terminate();
} else {
return Completable.timer(1, TimeUnit.SECONDS).andThen(getOrCreateWebSocketThread(hostname));
return Observable.timer(1, TimeUnit.SECONDS).toSingle()
.flatMap(_val -> disconnectFromServer(hostname));
}
}
webSocketThreads.put(hostname, null);
return RocketChatWebSocketThread.getStarted(getApplicationContext(), hostname)
.doOnSuccess(thread -> {
webSocketThreads.put(hostname, thread);
});
});
}
@DebugLog
private Single<RocketChatWebSocketThread> getOrCreateWebSocketThread(String hostname) {
return RxHelper.lazy(() -> {
if (webSocketThreads.containsKey(hostname)) {
RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
if (thread != null) {
return Single.just(thread);
} else {
return Observable.timer(1, TimeUnit.SECONDS).toSingle()
.flatMap(_val -> getOrCreateWebSocketThread(hostname));
}
}
webSocketThreads.put(hostname, null);
return RocketChatWebSocketThread.getStarted(getApplicationContext(), hostname)
.doOnSuccess(thread -> {
webSocketThreads.put(hostname, thread);
});
});
}
@Nullable
......
......@@ -32,8 +32,9 @@ import chat.rocket.android.service.observer.PushSettingsObserver;
import chat.rocket.android.service.observer.SessionObserver;
import chat.rocket.android.service.observer.TokenLoginObserver;
import hugo.weaving.DebugLog;
import rx.Completable;
import rx.Single;
import rx.SingleEmitter;
import rx.functions.Action1;
/**
* Thread for handling WebSocket connection.
......@@ -89,7 +90,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
}.start();
}).flatMap(webSocket ->
webSocket.connect().andThen(Single.just(webSocket)));
webSocket.connect().map(_val -> webSocket));
}
@Override
......@@ -115,23 +116,23 @@ public class RocketChatWebSocketThread extends HandlerThread {
* terminate WebSocket thread.
*/
@DebugLog
public Completable terminate() {
public Single<Boolean> terminate() {
if (isAlive()) {
return Completable.fromEmitter(completableEmitter -> {
return Single.fromEmitter(emitter -> {
new Handler(getLooper()).post(() -> {
RCLog.d("thread %s: terminated()", Thread.currentThread().getId());
unregisterListeners();
connectivityManager.notifyConnectionLost(hostname,
ConnectivityManagerInternal.REASON_CLOSED_BY_USER);
RocketChatWebSocketThread.super.quit();
completableEmitter.onCompleted();
emitter.onSuccess(true);
});
});
} else {
connectivityManager.notifyConnectionLost(hostname,
ConnectivityManagerInternal.REASON_NETWORK_ERROR);
super.quit();
return Completable.complete();
return Single.just(true);
}
}
......@@ -147,9 +148,9 @@ public class RocketChatWebSocketThread extends HandlerThread {
* synchronize the state of the thread with ServerConfig.
*/
@DebugLog
public Completable keepAlive() {
public Single<Boolean> keepAlive() {
return checkIfConnectionAlive()
.flatMapCompletable(alive -> alive ? Completable.complete() : connect());
.flatMap(alive -> alive ? Single.just(true) : connect());
}
private Single<Boolean> checkIfConnectionAlive() {
......@@ -157,27 +158,37 @@ public class RocketChatWebSocketThread extends HandlerThread {
return Single.just(false);
}
return Single.fromEmitter(booleanSingleEmitter -> {
ddpClient.ping().continueWith(task -> {
booleanSingleEmitter.onSuccess(!task.isFaulted());
return null;
});
return Single.fromEmitter(emitter -> {
new Thread() {
@Override
public void run() {
ddpClient.ping().continueWith(task -> {
if (task.isFaulted()) {
RCLog.e(task.getError());
emitter.onSuccess(false);
ddpClient.close();
} else {
emitter.onSuccess(true);
}
return null;
});
}
}.start();
});
}
private Completable prepareDDPClient() {
private Single<Boolean> prepareDDPClient() {
return checkIfConnectionAlive()
.doOnSuccess(alive -> {
if (!alive) {
ddpClient = DDPClientWrapper.create(hostname);
}
})
.toCompletable();
});
}
private Completable connectDDPClient() {
private Single<Boolean> connectDDPClient() {
return prepareDDPClient()
.andThen(Completable.fromEmitter(completableEmitter -> {
.flatMap(_val -> Single.fromEmitter(emitter -> {
ServerInfo info = connectivityManager.getServerInfoForHost(hostname);
ddpClient.connect(info.session, !info.insecure)
.onSuccessTask(task -> {
......@@ -203,9 +214,9 @@ public class RocketChatWebSocketThread extends HandlerThread {
})
.continueWith(task -> {
if (task.isFaulted()) {
completableEmitter.onError(task.getError());
emitter.onError(task.getError());
} else {
completableEmitter.onCompleted();
emitter.onSuccess(true);
}
return null;
});
......@@ -213,12 +224,15 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
@DebugLog
private Completable connect() {
private Single<Boolean> connect() {
return connectDDPClient()
.andThen(Completable.fromEmitter(completableEmitter -> {
fetchPublicSettings();
registerListeners();
completableEmitter.onCompleted();
.flatMap(_val -> Single.fromEmitter(new Action1<SingleEmitter<Boolean>>() {
@Override
public void call(SingleEmitter<Boolean> emitter) {
fetchPublicSettings();
registerListeners();
emitter.onSuccess(true);
}
}));
}
......
......@@ -33,7 +33,6 @@
<string name="fragment_login_password">Password</string>
<string name="fragment_retry_login_retry_title">RETRY</string>
<string name="fragment_retry_login_error_title">Connection Error</string>
<string name="add_server_activity_waiting_server">Connecting to server…</string>
<string name="server_config_activity_authenticating">Authenticating…</string>
<string name="home_fragment_title">Rocket.Chat - Home</string>
<string name="fragment_sidebar_main_unread_rooms_title">UNREAD ROOMS</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment