Commit 8b64b05b authored by Yusuke Iwaki's avatar Yusuke Iwaki Committed by GitHub

Merge branch 'develop' into feature/image-keyboard

parents 92b0eb83 41f255cc
......@@ -61,10 +61,6 @@ public class DDPClient {
return impl.getOnCloseCallback();
}
public boolean isConnected() {
return impl.isConnected();
}
public void close() {
impl.close(1000, "closed by DDPClient#close()");
}
......
......@@ -96,10 +96,6 @@ public class DDPClientImpl {
}
}
public boolean isConnected() {
return websocket != null && websocket.isConnected();
}
public void ping(final TaskCompletionSource<DDPClientCallback.Ping> task,
@Nullable final String id) {
......
......@@ -15,11 +15,9 @@ import rx.observables.ConnectableObservable;
public class RxWebSocket {
private OkHttpClient httpClient;
private WebSocket webSocket;
private boolean isConnected;
public RxWebSocket(OkHttpClient client) {
httpClient = client;
isConnected = false;
}
public ConnectableObservable<RxWebSocketCallback.Base> connect(String url) {
......@@ -31,7 +29,6 @@ public class RxWebSocket {
httpClient.newWebSocket(request, new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
isConnected = true;
RxWebSocket.this.webSocket = webSocket;
subscriber.onNext(new RxWebSocketCallback.Open(RxWebSocket.this.webSocket, response));
}
......@@ -39,7 +36,6 @@ public class RxWebSocket {
@Override
public void onFailure(WebSocket webSocket, Throwable err, Response response) {
try {
isConnected = false;
subscriber.onError(new RxWebSocketCallback.Failure(webSocket, err, response));
} catch (OnErrorNotImplementedException ex) {
RCLog.w(ex, "OnErrorNotImplementedException ignored");
......@@ -48,13 +44,11 @@ public class RxWebSocket {
@Override
public void onMessage(WebSocket webSocket, String text) {
isConnected = true;
subscriber.onNext(new RxWebSocketCallback.Message(webSocket, text));
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
isConnected = false;
subscriber.onNext(new RxWebSocketCallback.Close(webSocket, code, reason));
subscriber.onCompleted();
}
......@@ -67,10 +61,6 @@ public class RxWebSocket {
return webSocket.send(message);
}
public boolean isConnected() {
return isConnected;
}
public boolean close(int code, String reason) throws IOException {
return webSocket.close(code, reason);
}
......
......@@ -114,8 +114,8 @@ dependencies {
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
compile 'com.uphyca:stetho_realm:2.0.1'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0'
compile 'com.jakewharton.rxbinding:rxbinding:1.0.0'
compile 'com.jakewharton.rxbinding:rxbinding-support-v4:1.0.0'
compile 'com.trello:rxlifecycle:1.0'
compile 'com.trello:rxlifecycle-android:1.0'
......
......@@ -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(LoginActivity.KEY_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,23 +7,20 @@ 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.RocketChatService;
import chat.rocket.android.service.ConnectivityManager;
/**
* Activity for Login, Sign-up, and Retry connecting...
*/
public class LoginActivity extends AbstractFragmentActivity {
public static final String KEY_HOSTNAME = "hostname";
private String serverConfigId;
private RealmObjectObserver<ServerConfig> serverConfigErrorObserver;
private String hostname;
private RealmObjectObserver<Session> sessionObserver;
@Override
......@@ -41,53 +38,35 @@ public class LoginActivity extends AbstractFragmentActivity {
return;
}
serverConfigId = intent.getStringExtra(ServerConfig.ID);
if (TextUtils.isEmpty(serverConfigId)) {
hostname = intent.getStringExtra(KEY_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();
showFragment(new LoginFragment());
}
@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());
return;
}
......@@ -101,28 +80,26 @@ public class LoginActivity extends AbstractFragmentActivity {
}
return;
}
showFragment(new LoginFragment());
}
@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(LoginActivity.KEY_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,7 @@ 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())));
Session.retryLogin(RealmStore.get(hostname))));
} else if (!session.isTokenVerified()) {
statusTicker.updateStatus(StatusTicker.STATUS_TOKEN_LOGIN,
Snackbar.make(findViewById(getLayoutContainerForFragment()),
......@@ -219,11 +217,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 +251,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 +259,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());
......
package chat.rocket.android.api;
import android.support.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.UUID;
import bolts.Task;
import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.helper.TextUtils;
......@@ -9,11 +12,6 @@ import chat.rocket.android.log.RCLog;
import chat.rocket.android_ddp.DDPClient;
import chat.rocket.android_ddp.DDPClientCallback;
import chat.rocket.android_ddp.DDPSubscription;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONException;
import rx.Observable;
/**
......@@ -44,13 +42,6 @@ public class DDPClientWrapper {
return ddpClient.connect(protocol + hostname + "/websocket", session);
}
/**
* Returns whether DDP client is connected to WebSocket server.
*/
public boolean isConnected() {
return ddpClient.isConnected();
}
/**
* close connection.
*/
......@@ -82,10 +73,6 @@ public class DDPClientWrapper {
return ddpClient.getSubscriptionCallback();
}
private String generateId(String method) {
return method + "-" + UUID.randomUUID().toString().replace("-", "");
}
/**
* Execute raw RPC.
*/
......@@ -117,4 +104,22 @@ public class DDPClientWrapper {
return Task.forError(exception);
}
}
/**
* check WebSocket connectivity with ping.
*/
public Task<Void> ping() {
final String pingId = UUID.randomUUID().toString();
RCLog.d("ping[%s] >", pingId);
return ddpClient.ping(pingId)
.continueWithTask(task -> {
if (task.isFaulted()) {
RCLog.d(task.getError(), "ping[%s] xxx failed xxx", pingId);
return Task.forError(task.getError());
} else {
RCLog.d("pong[%s] <", pingId);
return Task.forResult(null);
}
});
}
}
......@@ -7,17 +7,18 @@ import org.json.JSONObject;
import bolts.Task;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* 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) {
super(realmHelper, ddpClient);
public FileUploadingHelper(RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(realmHelper, ddpClientRef);
}
public Task<JSONObject> uploadRequest(String filename, long filesize, String mimeType,
......
......@@ -19,6 +19,7 @@ import chat.rocket.android.model.internal.MethodCall;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android_ddp.DDPClientCallback;
import hugo.weaving.DebugLog;
......@@ -36,30 +37,30 @@ public class MethodCallHelper {
task -> Task.forResult(new JSONArray(task.getResult()));
protected final Context context;
protected final RealmHelper realmHelper;
protected final DDPClientWrapper ddpClient;
protected final DDPClientRef ddpClientRef;
/**
* 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);
ddpClient = null;
this.realmHelper = RealmStore.get(hostname);
ddpClientRef = null;
}
/**
* initialize with RealmHelper and DDPClient.
*/
public MethodCallHelper(RealmHelper realmHelper, DDPClientWrapper ddpClient) {
public MethodCallHelper(RealmHelper realmHelper, DDPClientRef ddpClientRef) {
this.context = null;
this.realmHelper = realmHelper;
this.ddpClient = ddpClient;
this.ddpClientRef = ddpClientRef;
}
@DebugLog
private Task<String> executeMethodCall(String methodName, String param, long timeout) {
if (ddpClient != null) {
return ddpClient.rpc(UUID.randomUUID().toString(), methodName, param, timeout)
if (ddpClientRef != null) {
return ddpClientRef.get().rpc(UUID.randomUUID().toString(), methodName, param, timeout)
.onSuccessTask(task -> Task.forResult(task.getResult().result));
} else {
return MethodCall.execute(context, realmHelper, methodName, param, timeout);
......
......@@ -8,15 +8,16 @@ import org.json.JSONObject;
import bolts.Task;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
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,
DDPClientWrapper ddpClient) {
super(realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(realmHelper, ddpClientRef);
}
public Task<Void> pushUpdate(@NonNull String pushId, @NonNull String gcmToken,
......
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());
}
}
}
......@@ -39,9 +39,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;
......@@ -50,7 +50,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;
......@@ -61,7 +60,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;
......@@ -77,11 +76,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;
......@@ -108,9 +106,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);
......@@ -122,14 +120,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 ->
......@@ -287,7 +280,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();
});
......@@ -345,7 +338,7 @@ public class RoomFragment extends AbstractChatRoomFragment
String uplId = new FileUploadHelper(getContext(), realmHelper)
.requestUploading(roomId, uri);
if (!TextUtils.isEmpty(uplId)) {
FileUploadProgressDialogFragment.create(serverConfigId, roomId, uplId)
FileUploadProgressDialogFragment.create(hostname, roomId, uplId)
.show(getFragmentManager(), FileUploadProgressDialogFragment.class.getSimpleName());
} else {
// show error.
......@@ -404,7 +397,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());
}
......@@ -425,7 +419,8 @@ public class RoomFragment extends AbstractChatRoomFragment
}
return null;
}).onSuccessTask(task -> {
RocketChatService.keepAlive(getContext());
ConnectivityManager.getInstance(getContext().getApplicationContext())
.keepAliveServer();
return task;
}).continueWith(new LogcatIfError());
}
......@@ -434,7 +429,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());
}
......
......@@ -5,11 +5,12 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import chat.rocket.android.R;
import chat.rocket.android.activity.LoginActivity;
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 +22,8 @@ abstract class AbstractServerConfigFragment extends AbstractFragment {
return;
}
serverConfigId = args.getString("serverConfigId");
if (TextUtils.isEmpty(serverConfigId)) {
hostname = args.getString(LoginActivity.KEY_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!
......
package chat.rocket.android.fragment.server_config;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.helper.TextUtils;
/**
* Just showing "connecting..." screen.
*/
public class WaitingFragment extends AbstractServerConfigFragment {
private String caption;
public WaitingFragment() {
}
/**
* create new "Waiting..." screen with caption.
*/
public static WaitingFragment create(String caption) {
Bundle args = new Bundle();
args.putString("caption", caption);
WaitingFragment fragment = new WaitingFragment();
fragment.setArguments(args);
return fragment;
}
@Override
protected int getLayout() {
return R.layout.fragment_waiting;
}
@Override
protected void onSetupView() {
Bundle args = getArguments();
if (args != null) {
caption = args.getString("caption");
}
TextView captionView = (TextView) rootView.findViewById(R.id.txt_caption);
if (TextUtils.isEmpty(caption)) {
captionView.setVisibility(View.GONE);
} else {
captionView.setText(caption);
captionView.setVisibility(View.VISIBLE);
}
}
}
......@@ -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;
}
......@@ -188,11 +179,11 @@ public class SidebarMainFragment extends AbstractFragment {
private void setupAddChannelButton() {
rootView.findViewById(R.id.btn_add_channel).setOnClickListener(view -> {
showAddRoomDialog(new AddChannelDialogFragment());
showAddRoomDialog(AddChannelDialogFragment.create(hostname));
});
rootView.findViewById(R.id.btn_add_direct_message).setOnClickListener(view -> {
showAddRoomDialog(new AddDirectMessageDialogFragment());
showAddRoomDialog(AddDirectMessageDialogFragment.create(hostname));
});
}
......@@ -202,10 +193,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());
}
......
......@@ -21,9 +21,7 @@ public abstract class AbstractAddRoomDialogFragment extends RxAppCompatDialogFra
protected MethodCallHelper methodCall;
protected String hostname;
protected
@LayoutRes
abstract int getLayout();
protected @LayoutRes abstract int getLayout();
protected abstract void onSetupDialog();
......@@ -38,10 +36,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.fragment.sidebar.dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.TextView;
......@@ -17,6 +18,15 @@ public class AddChannelDialogFragment extends AbstractAddRoomDialogFragment {
public AddChannelDialogFragment() {
}
public static AddChannelDialogFragment create(String hostname) {
Bundle args = new Bundle();
args.putString("hostname", hostname);
AddChannelDialogFragment fragment = new AddChannelDialogFragment();
fragment.setArguments(args);
return fragment;
}
@Override
protected int getLayout() {
return R.layout.dialog_add_channel;
......
package chat.rocket.android.fragment.sidebar.dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
......@@ -18,7 +19,13 @@ import chat.rocket.android.realm_helper.RealmAutoCompleteAdapter;
* add Direct Message.
*/
public class AddDirectMessageDialogFragment extends AbstractAddRoomDialogFragment {
public AddDirectMessageDialogFragment() {
public static AddDirectMessageDialogFragment create(String hostname) {
Bundle args = new Bundle();
args.putString("hostname", hostname);
AddDirectMessageDialogFragment fragment = new AddDirectMessageDialogFragment();
fragment.setArguments(args);
return fragment;
}
@Override
......
package chat.rocket.android.helper;
import java.util.concurrent.TimeUnit;
import rx.Observable;
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) {
// ref: https://github.com/ReactiveX/RxJava/blob/a8ba158839b67246a742b6f1531995ffd7545c08/src/main/java/io/reactivex/Observable.java#L9601
return attempts -> attempts
.zipWith(Observable.range(0, maxRetryCount), (error, retryCount) -> retryCount)
.flatMap(retryCount -> Observable.timer(base * (long) Math.pow(2, retryCount), unit));
}
}
......@@ -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;
import org.json.JSONObject;
import bolts.Task;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.realm_helper.RealmStore;
import hugo.weaving.DebugLog;
/**
* Server configuration.
*/
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;
/**
* Log the server connection is lost due to some exception.
*/
@DebugLog
public static void logConnectionError(String serverConfigId, Exception exception) {
RealmStore.getDefault().executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put(ID, serverConfigId)
.put(STATE, STATE_CONNECTION_ERROR)
.put(ERROR, exception.getMessage())))
.continueWith(new LogcatIfError());
}
/**
* Update the state of the ServerConfig with serverConfigId.
*/
public static Task<Void> updateState(final String serverConfigId, int state) {
return RealmStore.getDefault().executeTransaction(realm -> {
ServerConfig config =
realm.where(ServerConfig.class).equalTo(ID, serverConfigId).findFirst();
if (config == null || config.getState() != state) {
realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put(ID, serverConfigId)
.put(STATE, state));
}
return null;
});
}
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;
......
......@@ -55,6 +55,24 @@ public class Session extends RealmObject {
}
}
/**
* retry authentication.
*/
@DebugLog
public static void retryLogin(RealmHelper realmHelper) {
final Session session = realmHelper.executeTransactionForRead(realm ->
queryDefaultSession(realm).isNotNull(TOKEN).findFirst());
if (!session.isTokenVerified() || !TextUtils.isEmpty(session.getError())) {
realmHelper.executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(Session.class, new JSONObject()
.put(ID, Session.DEFAULT_ID)
.put(TOKEN_VERIFIED, false)
.put(ERROR, JSONObject.NULL)))
.continueWith(new LogcatIfError());
}
}
public int getSessionId() {
return sessionId;
}
......
......@@ -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);
}
package chat.rocket.android.service;
import android.content.Context;
/**
* Connectivity Manager API Factory.
*/
public class ConnectivityManager {
private static final RealmBasedConnectivityManager IMPL = new RealmBasedConnectivityManager();
public static ConnectivityManagerApi getInstance(Context appContext) {
return IMPL.setContext(appContext);
}
/*package*/ static ConnectivityManagerInternal getInstanceForInternal(Context appContext) {
return IMPL.setContext(appContext);
}
}
package chat.rocket.android.service;
import android.support.annotation.Nullable;
import java.util.List;
import rx.Observable;
import rx.Single;
/**
* interfaces used for Activity/Fragment and other UI-related logic.
*/
public interface ConnectivityManagerApi {
void keepAliveServer();
void addOrUpdateServer(String hostname, @Nullable String name, boolean insecure);
void removeServer(String hostname);
Single<Boolean> connect(String hostname);
List<ServerInfo> getServerList();
Observable<ServerConnectivity> getServerConnectivityAsObservable();
}
package chat.rocket.android.service;
import java.util.List;
/**
* interfaces used for RocketChatService and RocketChatwebSocketThread.
*/
/*package*/ interface ConnectivityManagerInternal {
int REASON_CLOSED_BY_USER = 101;
int REASON_NETWORK_ERROR = 102;
int REASON_SERVER_ERROR = 103;
int REASON_UNKNOWN = 104;
void resetConnectivityStateList();
void ensureConnections();
List<ServerInfo> getServerList();
ServerInfo getServerInfoForHost(String hostname);
void notifyConnectionEstablished(String hostname, String session);
void notifyConnectionLost(String hostname, int reason);
}
package chat.rocket.android.service;
import rx.Single;
public interface ConnectivityServiceInterface {
Single<Boolean> ensureConnectionToServer(String hostname);
Single<Boolean> disconnectFromServer(String hostname);
}
package chat.rocket.android.service;
import chat.rocket.android.api.DDPClientWrapper;
/**
* reference to get fresh DDPClient instance.
*/
public interface DDPClientRef {
DDPClientWrapper get();
}
package chat.rocket.android.service;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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 RealmBasedConnectivityManager
implements ConnectivityManagerApi, ConnectivityManagerInternal {
private final HashMap<String, Integer> serverConnectivityList = new HashMap<>();
private final PublishSubject<ServerConnectivity> connectivitySubject = PublishSubject.create();
private Context appContext;
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder binder) {
serviceInterface = ((RocketChatService.LocalBinder) binder).getServiceInterface();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
serviceInterface = null;
}
};
private ConnectivityServiceInterface serviceInterface;
/*package*/ RealmBasedConnectivityManager setContext(Context appContext) {
this.appContext = appContext;
return this;
}
@Override
public void resetConnectivityStateList() {
serverConnectivityList.clear();
for (ServerInfo serverInfo : RealmBasedServerInfo.getServerInfoList()) {
serverConnectivityList.put(serverInfo.hostname, ServerConnectivity.STATE_DISCONNECTED);
}
}
@Override
public void keepAliveServer() {
RocketChatService.keepAlive(appContext);
if (serviceInterface == null) {
RocketChatService.bind(appContext, serviceConnection);
}
}
@Override
public void ensureConnections() {
for (String hostname : serverConnectivityList.keySet()) {
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, boolean insecure) {
RealmBasedServerInfo.addOrUpdate(hostname, name);
RealmBasedServerInfo.setInsecure(hostname, insecure);
if (!serverConnectivityList.containsKey(hostname)) {
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTED);
}
connectToServerIfNeeded(hostname)
.subscribe(_val -> { }, RCLog::e);
}
@Override
public void removeServer(String hostname) {
RealmBasedServerInfo.remove(hostname);
if (serverConnectivityList.containsKey(hostname)) {
disconnectFromServerIfNeeded(hostname)
.subscribe(_val -> { }, RCLog::e);
}
}
@Override
public Single<Boolean> connect(String hostname) {
return connectToServerIfNeeded(hostname);
}
@Override
public List<ServerInfo> getServerList() {
return RealmBasedServerInfo.getServerInfoList();
}
@Override
public ServerInfo getServerInfoForHost(String hostname) {
return RealmBasedServerInfo.getServerInfoForHost(hostname);
}
private List<ServerConnectivity> getCurrentConnectivityList() {
ArrayList<ServerConnectivity> list = new ArrayList<>();
for (Map.Entry<String, Integer> entry : serverConnectivityList.entrySet()) {
list.add(new ServerConnectivity(entry.getKey(), entry.getValue()));
}
return list;
}
@DebugLog
@Override
public void notifyConnectionEstablished(String hostname, String session) {
RealmBasedServerInfo.updateSession(hostname, session);
serverConnectivityList.put(hostname, ServerConnectivity.STATE_CONNECTED);
connectivitySubject.onNext(
new ServerConnectivity(hostname, ServerConnectivity.STATE_CONNECTED));
}
@DebugLog
@Override
public void notifyConnectionLost(String hostname, int reason) {
serverConnectivityList.put(hostname, ServerConnectivity.STATE_DISCONNECTED);
connectivitySubject.onNext(
new ServerConnectivity(hostname, ServerConnectivity.STATE_DISCONNECTED));
}
@Override
public Observable<ServerConnectivity> getServerConnectivityAsObservable() {
return Observable.concat(Observable.from(getCurrentConnectivityList()), connectivitySubject);
}
private Single<Boolean> connectToServerIfNeeded(String hostname) {
return Single.defer(() -> {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_CONNECTED) {
return Single.just(true);
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname)
.flatMap(_val -> connectToServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname);
}
return connectToServer(hostname)
//.doOnError(RCLog::e)
.retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS));
});
}
private Single<Boolean> disconnectFromServerIfNeeded(String hostname) {
return Single.defer(() -> {
final int connectivity = serverConnectivityList.get(hostname);
if (connectivity == ServerConnectivity.STATE_DISCONNECTED) {
return Single.just(true);
}
if (connectivity == ServerConnectivity.STATE_CONNECTING) {
return waitForConnected(hostname)
.flatMap(_val -> disconnectFromServerIfNeeded(hostname));
}
if (connectivity == ServerConnectivity.STATE_DISCONNECTING) {
return waitForDisconnected(hostname);
}
return disconnectFromServer(hostname)
//.doOnError(RCLog::e)
.retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS));
});
}
private Single<Boolean> waitForConnected(String hostname) {
return connectivitySubject
.filter(serverConnectivity -> (hostname.equals(serverConnectivity.hostname)
&& serverConnectivity.state == ServerConnectivity.STATE_CONNECTED))
.first()
.map(serverConnectivity -> true)
.toSingle();
}
private Single<Boolean> waitForDisconnected(String hostname) {
return connectivitySubject
.filter(serverConnectivity -> (hostname.equals(serverConnectivity.hostname)
&& serverConnectivity.state == ServerConnectivity.STATE_DISCONNECTED))
.first()
.map(serverConnectivity -> true)
.toSingle();
}
private Single<Boolean> connectToServer(String hostname) {
return Single.defer(() -> {
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 Single.defer(() -> {
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 android.support.annotation.Nullable;
import android.text.TextUtils;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
/**
* Backend implementation to store ServerInfo.
*/
public class RealmBasedServerInfo extends RealmObject {
private static final String DB_NAME = "serverlist";
@PrimaryKey private String hostname;
private String name;
private String session;
private boolean insecure;
interface ColumnName {
String HOSTNAME = "hostname";
String NAME = "name";
String SESSION = "session";
String INSECURE = "insecure";
}
ServerInfo getServerInfo() {
return new ServerInfo(hostname, name, session, insecure);
}
static RealmHelper getRealm() {
return RealmStore.getOrCreate(DB_NAME);
}
static void addOrUpdate(String hostname, String name) {
getRealm().executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(RealmBasedServerInfo.class, new JSONObject()
.put(ColumnName.HOSTNAME, hostname)
.put(ColumnName.NAME, TextUtils.isEmpty(name) ? JSONObject.NULL : name)));
}
static void remove(String hostname) {
getRealm().executeTransaction(realm -> {
realm.where(RealmBasedServerInfo.class).equalTo(ColumnName.HOSTNAME, hostname)
.findAll()
.deleteAllFromRealm();
return null;
});
}
static void updateSession(String hostname, String session) {
RealmBasedServerInfo impl = getRealm().executeTransactionForRead(realm ->
realm.where(RealmBasedServerInfo.class).equalTo(ColumnName.HOSTNAME, hostname).findFirst());
if (impl != null) {
impl.session = session;
getRealm().executeTransaction(realm -> {
realm.copyToRealmOrUpdate(impl);
return null;
});
}
}
static @Nullable ServerInfo getServerInfoForHost(String hostname) {
RealmBasedServerInfo impl = getRealm().executeTransactionForRead(realm ->
realm.where(RealmBasedServerInfo.class).equalTo(ColumnName.HOSTNAME, hostname).findFirst());
return impl == null ? null : impl.getServerInfo();
}
static void setInsecure(String hostname, boolean insecure) {
RealmBasedServerInfo impl = getRealm().executeTransactionForRead(realm ->
realm.where(RealmBasedServerInfo.class).equalTo(ColumnName.HOSTNAME, hostname).findFirst());
if (impl != null) {
impl.insecure = insecure;
getRealm().executeTransaction(realm -> {
realm.copyToRealmOrUpdate(impl);
return null;
});
}
}
static List<ServerInfo> getServerInfoList() {
List<RealmBasedServerInfo> results = getRealm().executeTransactionForReadResults(realm ->
realm.where(RealmBasedServerInfo.class).findAll());
ArrayList<ServerInfo> list = new ArrayList<>();
for (RealmBasedServerInfo impl : results) {
list.add(impl.getServerInfo());
}
return list;
}
}
......@@ -3,140 +3,112 @@ package chat.rocket.android.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import io.realm.RealmResults;
import java.util.HashMap;
import java.util.List;
import bolts.Task;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.realm_helper.RealmStore;
import java.util.concurrent.TimeUnit;
import hugo.weaving.DebugLog;
import rx.Observable;
import rx.Single;
/**
* Background service for Rocket.Chat.Application class.
*/
public class RocketChatService extends Service {
public class RocketChatService extends Service implements ConnectivityServiceInterface {
private RealmHelper realmHelper;
private ConnectivityManagerInternal connectivityManager;
private HashMap<String, RocketChatWebSocketThread> webSocketThreads;
private RealmListObserver<ServerConfig> connectionRequiredServerConfigObserver;
public class LocalBinder extends Binder {
ConnectivityServiceInterface getServiceInterface() {
return RocketChatService.this;
}
}
private final LocalBinder localBinder = new LocalBinder();
/**
* ensure RocketChatService alive.
*/
public static void keepAlive(Context context) {
/*package*/ static void keepAlive(Context context) {
context.startService(new Intent(context, RocketChatService.class));
}
public static void bind(Context context, ServiceConnection serviceConnection) {
context.bindService(
new Intent(context, RocketChatService.class), serviceConnection, Context.BIND_AUTO_CREATE);
}
public static void unbind(Context context, ServiceConnection serviceConnection) {
context.unbindService(serviceConnection);
}
@Override
public void onCreate() {
super.onCreate();
webSocketThreads = new HashMap<>();
realmHelper = RealmStore.getDefault();
connectionRequiredServerConfigObserver = realmHelper
.createListObserver(realm -> realm.where(ServerConfig.class)
.isNotNull(ServerConfig.HOSTNAME)
.equalTo(ServerConfig.STATE, ServerConfig.STATE_READY)
.findAll())
.setOnUpdateListener(this::connectToServerWithServerConfig);
refreshServerConfigState();
}
private void refreshServerConfigState() {
realmHelper.executeTransaction(realm -> {
RealmResults<ServerConfig> configs = realm.where(ServerConfig.class)
.notEqualTo(ServerConfig.STATE, ServerConfig.STATE_READY)
.findAll();
for (ServerConfig config : configs) {
config.setState(ServerConfig.STATE_READY);
}
return null;
}).continueWith(new LogcatIfError());
;
connectivityManager = ConnectivityManager.getInstanceForInternal(getApplicationContext());
connectivityManager.resetConnectivityStateList();
webSocketThreads = new HashMap<>();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
List<ServerConfig> configs = realmHelper.executeTransactionForReadResults(realm ->
realm.where(ServerConfig.class)
.equalTo(ServerConfig.STATE, ServerConfig.STATE_CONNECTED)
.findAll());
for (ServerConfig config : configs) {
String serverConfigId = config.getServerConfigId();
if (webSocketThreads.containsKey(serverConfigId)) {
RocketChatWebSocketThread thread = webSocketThreads.get(serverConfigId);
if (thread != null) {
thread.keepAlive();
}
}
}
realmHelper.executeTransaction(realm -> {
RealmResults<ServerConfig> targetConfigs = realm
.where(ServerConfig.class)
.beginGroup()
.equalTo(ServerConfig.STATE, ServerConfig.STATE_CONNECTION_ERROR)
.or()
.isNotNull(ServerConfig.ERROR)
.endGroup()
.isNotNull(ServerConfig.SESSION)
.findAll();
for (ServerConfig config : targetConfigs) {
config.setState(ServerConfig.STATE_READY);
config.setError(null);
}
return null;
}).onSuccessTask(task -> {
connectionRequiredServerConfigObserver.sub();
return null;
});
connectivityManager.ensureConnections();
return START_NOT_STICKY;
}
private void connectToServerWithServerConfig(List<ServerConfig> configList) {
if (configList.isEmpty()) {
return;
}
ServerConfig config = configList.get(0);
final String serverConfigId = config.getServerConfigId();
ServerConfig.updateState(serverConfigId, ServerConfig.STATE_CONNECTING)
.onSuccessTask(task -> createWebSocketThread(config))
.onSuccessTask(task -> {
RocketChatWebSocketThread thread = task.getResult();
if (thread != null) {
thread.keepAlive();
}
return ServerConfig.updateState(serverConfigId, ServerConfig.STATE_CONNECTED);
}).continueWith(new LogcatIfError());
@Override
public Single<Boolean> ensureConnectionToServer(String hostname) { //called via binder.
return getOrCreateWebSocketThread(hostname)
.doOnError(err -> {
webSocketThreads.remove(hostname);
connectivityManager.notifyConnectionLost(hostname, ConnectivityManagerInternal.REASON_NETWORK_ERROR);
})
.flatMap(webSocketThreads -> webSocketThreads.keepAlive());
}
private Task<RocketChatWebSocketThread> createWebSocketThread(final ServerConfig config) {
final String serverConfigId = config.getServerConfigId();
webSocketThreads.put(serverConfigId, null);
return RocketChatWebSocketThread.getStarted(getApplicationContext(), config)
.onSuccessTask(task -> {
webSocketThreads.put(serverConfigId, task.getResult());
return task;
});
@Override
public Single<Boolean> disconnectFromServer(String hostname) { //called via binder.
return Single.defer(() -> {
if (!webSocketThreads.containsKey(hostname)) {
return Single.just(true);
}
RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
if (thread != null) {
return thread.terminate();
} else {
return Observable.timer(1, TimeUnit.SECONDS).toSingle()
.flatMap(_val -> disconnectFromServer(hostname));
}
});
}
@Override
public void onDestroy() {
if (connectionRequiredServerConfigObserver != null) {
connectionRequiredServerConfigObserver.unsub();
}
super.onDestroy();
@DebugLog
private Single<RocketChatWebSocketThread> getOrCreateWebSocketThread(String hostname) {
return Single.defer(() -> {
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
@Override
public IBinder onBind(Intent intent) {
return null;
return localBinder;
}
}
package chat.rocket.android.service;
/**
* pair with server's hostname and its connectivity state.
*/
public class ServerConnectivity {
public static final int STATE_CONNECTED = 1;
public static final int STATE_DISCONNECTED = 2;
/*package*/ static final int STATE_CONNECTING = 3;
/*package*/ static final int STATE_DISCONNECTING = 4;
public final String hostname;
public final int state;
public ServerConnectivity(String hostname, int state) {
this.hostname = hostname;
this.state = state;
}
}
package chat.rocket.android.service;
/**
* Stores information just for required for initializing connectivity manager.
*/
public class ServerInfo {
public final String hostname;
public final String name;
/*package*/ final String session;
public final boolean insecure;
public ServerInfo(String hostname, String name, String session, boolean insecure) {
this.hostname = hostname;
this.name = name;
this.session = session;
this.insecure = insecure;
}
}
......@@ -9,10 +9,10 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.Registrable;
import chat.rocket.android_ddp.DDPSubscription;
import rx.Subscription;
......@@ -21,17 +21,17 @@ public abstract class AbstractDDPDocEventSubscriber implements Registrable {
protected final Context context;
protected final String hostname;
protected final RealmHelper realmHelper;
protected final DDPClientWrapper ddpClient;
protected final DDPClientRef ddpClientRef;
private boolean isUnsubscribed;
private String subscriptionId;
private Subscription rxSubscription;
protected AbstractDDPDocEventSubscriber(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
this.context = context;
this.hostname = hostname;
this.realmHelper = realmHelper;
this.ddpClient = ddpClient;
this.ddpClientRef = ddpClientRef;
}
protected abstract String getSubscriptionName();
......@@ -66,9 +66,9 @@ public abstract class AbstractDDPDocEventSubscriber implements Registrable {
// just ignore.
}
ddpClient.subscribe(getSubscriptionName(), params).onSuccess(task -> {
ddpClientRef.get().subscribe(getSubscriptionName(), params).onSuccess(task -> {
if (isUnsubscribed) {
ddpClient.unsubscribe(task.getResult().id).continueWith(new LogcatIfError());
ddpClientRef.get().unsubscribe(task.getResult().id).continueWith(new LogcatIfError());
} else {
subscriptionId = task.getResult().id;
}
......@@ -95,7 +95,7 @@ public abstract class AbstractDDPDocEventSubscriber implements Registrable {
}
protected Subscription subscribe() {
return ddpClient.getSubscriptionCallback()
return ddpClientRef.get().getSubscriptionCallback()
.filter(event -> event instanceof DDPSubscription.DocEvent)
.cast(DDPSubscription.DocEvent.class)
.filter(event -> isTarget(event.collection))
......@@ -182,7 +182,7 @@ public abstract class AbstractDDPDocEventSubscriber implements Registrable {
rxSubscription.unsubscribe();
}
if (!TextUtils.isEmpty(subscriptionId)) {
ddpClient.unsubscribe(subscriptionId).continueWith(new LogcatIfError());
ddpClientRef.get().unsubscribe(subscriptionId).continueWith(new LogcatIfError());
}
}
}
......@@ -3,14 +3,14 @@ package chat.rocket.android.service.ddp.base;
import android.content.Context;
import org.json.JSONArray;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.ddp.AbstractDDPDocEventSubscriber;
abstract class AbstractBaseSubscriber extends AbstractDDPDocEventSubscriber {
protected AbstractBaseSubscriber(Context context, String hostname, RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -2,21 +2,20 @@ package chat.rocket.android.service.ddp.base;
import android.content.Context;
import io.realm.RealmObject;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* "activeUsers" subscriber.
*/
public class ActiveUsersSubscriber extends AbstractBaseSubscriber {
public ActiveUsersSubscriber(Context context, String hostname, RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -3,17 +3,17 @@ package chat.rocket.android.service.ddp.base;
import android.content.Context;
import io.realm.RealmObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* meteor.loginServiceConfiguration subscriber
*/
public class LoginServiceConfigurationSubscriber extends AbstractBaseSubscriber {
public LoginServiceConfigurationSubscriber(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -2,21 +2,20 @@ package chat.rocket.android.service.ddp.base;
import android.content.Context;
import io.realm.RealmObject;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* "userData" subscriber.
*/
public class UserDataSubscriber extends AbstractBaseSubscriber {
public UserDataSubscriber(Context context, String hostname, RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -5,18 +5,18 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.ddp.AbstractDDPDocEventSubscriber;
import chat.rocket.android_ddp.DDPSubscription;
abstract class AbstractStreamNotifyEventSubscriber extends AbstractDDPDocEventSubscriber {
protected AbstractStreamNotifyEventSubscriber(Context context, String hostname,
RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -2,16 +2,16 @@ package chat.rocket.android.service.ddp.stream;
import android.content.Context;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
abstract class AbstractStreamNotifyUserEventSubscriber extends AbstractStreamNotifyEventSubscriber {
protected final String userId;
protected AbstractStreamNotifyUserEventSubscriber(Context context, String hostname,
RealmHelper realmHelper,
DDPClientWrapper ddpClient, String userId) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef, String userId) {
super(context, hostname, realmHelper, ddpClientRef);
this.userId = userId;
}
......
......@@ -5,15 +5,15 @@ import io.realm.RealmObject;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
public class StreamNotifyUserSubscriptionsChanged extends AbstractStreamNotifyUserEventSubscriber {
public StreamNotifyUserSubscriptionsChanged(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient,
RealmHelper realmHelper, DDPClientRef ddpClientRef,
String userId) {
super(context, hostname, realmHelper, ddpClient, userId);
super(context, hostname, realmHelper, ddpClientRef, userId);
}
@Override
......
......@@ -5,9 +5,9 @@ import io.realm.RealmObject;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* stream-room-message subscriber.
......@@ -16,8 +16,8 @@ public class StreamRoomMessage extends AbstractStreamNotifyEventSubscriber {
private String roomId;
public StreamRoomMessage(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient, String roomId) {
super(context, hostname, realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef, String roomId) {
super(context, hostname, realmHelper, ddpClientRef);
this.roomId = roomId;
}
......
......@@ -4,8 +4,8 @@ import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.Registrable;
import chat.rocket.android.service.ddp.stream.StreamRoomMessage;
......@@ -16,17 +16,17 @@ public class StreamRoomMessageManager implements Registrable {
private final Context context;
private final String hostname;
private final RealmHelper realmHelper;
private final DDPClientWrapper ddpClient;
private final DDPClientRef ddpClientRef;
private final AbstractRocketChatCacheObserver cacheObserver;
private final Handler handler;
private StreamRoomMessage streamRoomMessage;
public StreamRoomMessageManager(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
this.context = context;
this.hostname = hostname;
this.realmHelper = realmHelper;
this.ddpClient = ddpClient;
this.ddpClientRef = ddpClientRef;
cacheObserver = new AbstractRocketChatCacheObserver(context, realmHelper) {
@Override
......@@ -40,7 +40,7 @@ public class StreamRoomMessageManager implements Registrable {
private void registerStreamNotifyMessage(String roomId) {
handler.post(() -> {
streamRoomMessage = new StreamRoomMessage(context, hostname, realmHelper, ddpClient, roomId);
streamRoomMessage = new StreamRoomMessage(context, hostname, realmHelper, ddpClientRef, roomId);
streamRoomMessage.register();
});
}
......
......@@ -3,9 +3,9 @@ package chat.rocket.android.service.observer;
import android.content.Context;
import io.realm.RealmObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.Registrable;
abstract class AbstractModelObserver<T extends RealmObject>
......@@ -14,15 +14,15 @@ abstract class AbstractModelObserver<T extends RealmObject>
protected final Context context;
protected final String hostname;
protected final RealmHelper realmHelper;
protected final DDPClientWrapper ddpClient;
protected final DDPClientRef ddpClientRef;
private final RealmListObserver observer;
protected AbstractModelObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
this.context = context;
this.hostname = hostname;
this.realmHelper = realmHelper;
this.ddpClient = ddpClient;
this.ddpClientRef = ddpClientRef;
observer = realmHelper.createListObserver(this).setOnUpdateListener(this);
}
......
......@@ -6,11 +6,11 @@ import io.realm.RealmResults;
import java.util.ArrayList;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.Registrable;
import chat.rocket.android.service.ddp.stream.StreamNotifyUserSubscriptionsChanged;
import hugo.weaving.DebugLog;
......@@ -24,9 +24,9 @@ public class CurrentUserObserver extends AbstractModelObserver<User> {
private ArrayList<Registrable> listeners;
public CurrentUserObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new MethodCallHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new MethodCallHelper(realmHelper, ddpClientRef);
currentUserExists = false;
}
......@@ -62,7 +62,7 @@ public class CurrentUserObserver extends AbstractModelObserver<User> {
methodCall.getRoomSubscriptions().onSuccess(task -> {
if (listeners != null) {
Registrable listener = new StreamNotifyUserSubscriptionsChanged(
context, hostname, realmHelper, ddpClient, userId);
context, hostname, realmHelper, ddpClientRef, userId);
listener.register();
listeners.add(listener);
}
......
......@@ -11,7 +11,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import bolts.Task;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.FileUploadingHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.OkHttpHelper;
......@@ -19,6 +18,7 @@ import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.internal.FileUploading;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
......@@ -35,9 +35,9 @@ public class FileUploadingToS3Observer extends AbstractModelObserver<FileUploadi
private FileUploadingHelper methodCall;
public FileUploadingToS3Observer(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new FileUploadingHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new FileUploadingHelper(realmHelper, ddpClientRef);
realmHelper.executeTransaction(realm -> {
// resume pending operations.
......
......@@ -9,7 +9,6 @@ import org.json.JSONObject;
import java.io.InputStream;
import java.util.List;
import bolts.Task;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.FileUploadingHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.OkHttpHelper;
......@@ -19,6 +18,7 @@ import chat.rocket.android.model.ddp.User;
import chat.rocket.android.model.internal.FileUploading;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
......@@ -31,9 +31,9 @@ public class FileUploadingWithUfsObserver extends AbstractModelObserver<FileUplo
private FileUploadingHelper methodCall;
public FileUploadingWithUfsObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new FileUploadingHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new FileUploadingHelper(realmHelper, ddpClientRef);
realmHelper.executeTransaction(realm -> {
// resume pending operations.
......
......@@ -11,7 +11,6 @@ import java.io.IOException;
import java.util.List;
import bolts.Task;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.RaixPushHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.SyncState;
......@@ -20,6 +19,7 @@ import chat.rocket.android.model.ddp.PublicSettingsConstants;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.model.internal.GcmPushRegistration;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* call raix:push-update if needed.
......@@ -27,8 +27,8 @@ import chat.rocket.android.realm_helper.RealmHelper;
public class GcmPushRegistrationObserver extends AbstractModelObserver<GcmPushRegistration> {
public GcmPushRegistrationObserver(Context context, String hostname,
RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......@@ -75,7 +75,7 @@ public class GcmPushRegistrationObserver extends AbstractModelObserver<GcmPushRe
final String userId = currentUser != null ? currentUser.getId() : null;
final String pushId = RocketChatCache.getOrCreatePushId(context);
return new RaixPushHelper(realmHelper, ddpClient)
return new RaixPushHelper(realmHelper, ddpClientRef)
.pushUpdate(pushId, gcmToken, userId);
}
......
......@@ -7,12 +7,12 @@ import org.json.JSONObject;
import java.util.List;
import bolts.Task;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.MethodCallHelper;
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.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* Model observer for executing getUsersOfRooms.
......@@ -23,9 +23,9 @@ public class GetUsersOfRoomsProcedureObserver
private final MethodCallHelper methodCall;
public GetUsersOfRoomsProcedureObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new MethodCallHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new MethodCallHelper(realmHelper, ddpClientRef);
}
@Override
......
......@@ -8,13 +8,13 @@ import org.json.JSONObject;
import java.util.List;
import bolts.Task;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.model.internal.LoadMessageProcedure;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* Background process for loading messages.
......@@ -24,9 +24,9 @@ public class LoadMessageProcedureObserver extends AbstractModelObserver<LoadMess
private final MethodCallHelper methodCall;
public LoadMessageProcedureObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new MethodCallHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new MethodCallHelper(realmHelper, ddpClientRef);
}
@Override
......
......@@ -6,12 +6,12 @@ import io.realm.RealmResults;
import org.json.JSONObject;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.CheckSum;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.internal.MethodCall;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android_ddp.DDPClientCallback;
/**
......@@ -25,8 +25,8 @@ public class MethodCallObserver extends AbstractModelObserver<MethodCall> {
* constructor.
*/
public MethodCallObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
realmHelper.executeTransaction(realm -> {
// resume pending operations.
RealmResults<MethodCall> pendingMethodCalls = realm.where(MethodCall.class)
......@@ -97,7 +97,7 @@ public class MethodCallObserver extends AbstractModelObserver<MethodCall> {
.put(MethodCall.ID, methodCallId)
.put(MethodCall.SYNC_STATE, SyncState.SYNCING))
).onSuccessTask(task ->
ddpClient.rpc(methodCallId, methodName, params, timeout)
ddpClientRef.get().rpc(methodCallId, methodName, params, timeout)
.onSuccessTask(_task -> realmHelper.executeTransaction(realm -> {
String json = _task.getResult().result;
return realm.createOrUpdateObjectFromJson(MethodCall.class, new JSONObject()
......
......@@ -6,13 +6,13 @@ import io.realm.RealmResults;
import org.json.JSONObject;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
/**
* Observe messages for sending.
......@@ -22,9 +22,9 @@ public class NewMessageObserver extends AbstractModelObserver<Message> {
private final MethodCallHelper methodCall;
public NewMessageObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new MethodCallHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new MethodCallHelper(realmHelper, ddpClientRef);
realmHelper.executeTransaction(realm -> {
// resume pending operations.
......
......@@ -5,17 +5,17 @@ import io.realm.Realm;
import io.realm.RealmResults;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.GcmPushSettingHelper;
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.service.DDPClientRef;
public class PushSettingsObserver extends AbstractModelObserver<PublicSetting> {
public PushSettingsObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
}
@Override
......
......@@ -6,7 +6,6 @@ import io.realm.RealmResults;
import java.util.List;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.RaixPushHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.internal.GetUsersOfRoomsProcedure;
......@@ -14,6 +13,7 @@ import chat.rocket.android.model.internal.LoadMessageProcedure;
import chat.rocket.android.model.internal.MethodCall;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.android.service.internal.StreamRoomMessageManager;
import hugo.weaving.DebugLog;
......@@ -29,12 +29,12 @@ public class SessionObserver extends AbstractModelObserver<Session> {
* constructor.
*/
public SessionObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
count = 0;
streamNotifyMessage = new StreamRoomMessageManager(context, hostname, realmHelper, ddpClient);
pushHelper = new RaixPushHelper(realmHelper, ddpClient);
streamNotifyMessage = new StreamRoomMessageManager(context, hostname, realmHelper, ddpClientRef);
pushHelper = new RaixPushHelper(realmHelper, ddpClientRef);
}
@Override
......
......@@ -5,20 +5,20 @@ import io.realm.Realm;
import io.realm.RealmResults;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
public class TokenLoginObserver extends AbstractModelObserver<Session> {
private final MethodCallHelper methodCall;
public TokenLoginObserver(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
methodCall = new MethodCallHelper(realmHelper, ddpClient);
RealmHelper realmHelper, DDPClientRef ddpClientRef) {
super(context, hostname, realmHelper, ddpClientRef);
methodCall = new MethodCallHelper(realmHelper, ddpClientRef);
}
@Override
......
......@@ -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>
......
......@@ -14,7 +14,7 @@ ext {
supportV13 = "com.android.support:support-v13:$supportVersion"
supportDesign = "com.android.support:design:$supportVersion"
rxJava = 'io.reactivex:rxjava:1.2.2'
rxJava = 'io.reactivex:rxjava:1.2.3'
boltsTask = 'com.parse.bolts:bolts-tasks:1.4.0'
okhttp3 = 'com.squareup.okhttp3:okhttp:3.5.0'
picasso = 'com.squareup.picasso:picasso:2.5.2'
......
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