Commit 9bb20414 authored by Yusuke Iwaki's avatar Yusuke Iwaki

fix application codes to pass "./gradlew check"

parent 4d8862e4
...@@ -5,7 +5,13 @@ import android.content.Intent; ...@@ -5,7 +5,13 @@ import android.content.Intent;
import chat.rocket.android.activity.ServerConfigActivity; import chat.rocket.android.activity.ServerConfigActivity;
/**
* utility class for launching Activity
*/
public class LaunchUtil { public class LaunchUtil {
/**
* launc ServerConfigActivity with proper flags.
*/
public static void showServerConfigActivity(Context context, String id) { public static void showServerConfigActivity(Context context, String id) {
Intent intent = new Intent(context, ServerConfigActivity.class); Intent intent = new Intent(context, ServerConfigActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
......
...@@ -9,6 +9,9 @@ import io.realm.Realm; ...@@ -9,6 +9,9 @@ import io.realm.Realm;
import io.realm.RealmConfiguration; import io.realm.RealmConfiguration;
import timber.log.Timber; import timber.log.Timber;
/**
* Customized Application-class for Rocket.Chat
*/
public class RocketChatApplication extends Application { public class RocketChatApplication extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
......
...@@ -15,7 +15,8 @@ import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts; ...@@ -15,7 +15,8 @@ import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
abstract class AbstractAuthedActivity extends AppCompatActivity { abstract class AbstractAuthedActivity extends AppCompatActivity {
private RealmListObserver<ServerConfig> mInsertEmptyRecordIfNoConfigurationExists = new RealmListObserver<ServerConfig>() { private RealmListObserver<ServerConfig> mInsertEmptyRecordIfNoConfigurationExists =
new RealmListObserver<ServerConfig>() {
@Override @Override
protected RealmResults<ServerConfig> queryItems(Realm realm) { protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class).findAll(); return realm.where(ServerConfig.class).findAll();
...@@ -26,14 +27,15 @@ abstract class AbstractAuthedActivity extends AppCompatActivity { ...@@ -26,14 +27,15 @@ abstract class AbstractAuthedActivity extends AppCompatActivity {
if (list.isEmpty()) { if (list.isEmpty()) {
final String newId = UUID.randomUUID().toString(); final String newId = UUID.randomUUID().toString();
RealmHelperBolts RealmHelperBolts
.executeTransaction(realm -> realm.createObject(ServerConfig.class, newId)) .executeTransaction(realm ->
realm.createObject(ServerConfig.class, newId))
.continueWith(new LogcatIfError()); .continueWith(new LogcatIfError());
} }
} }
}; };
private RealmListObserver<ServerConfig> mShowConfigActivityIfNeeded = new RealmListObserver<ServerConfig>() { private RealmListObserver<ServerConfig> mShowConfigActivityIfNeeded =
new RealmListObserver<ServerConfig>() {
@Override @Override
protected RealmResults<ServerConfig> queryItems(Realm realm) { protected RealmResults<ServerConfig> queryItems(Realm realm) {
return ServerConfig.queryLoginRequiredConnections(realm).findAll(); return ServerConfig.queryLoginRequiredConnections(realm).findAll();
......
...@@ -11,13 +11,11 @@ abstract class AbstractFragmentActivity extends AppCompatActivity { ...@@ -11,13 +11,11 @@ abstract class AbstractFragmentActivity extends AppCompatActivity {
protected abstract @IdRes int getLayoutContainerForFragment(); protected abstract @IdRes int getLayoutContainerForFragment();
@Override @Override
public void onBackPressed(){ public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(getLayoutContainerForFragment()); Fragment f = getSupportFragmentManager().findFragmentById(getLayoutContainerForFragment());
if(f instanceof OnBackPressListener && if (f instanceof OnBackPressListener && ((OnBackPressListener) f).onBackPressed()) {
((OnBackPressListener) f).onBackPressed()){
//consumed. do nothing. //consumed. do nothing.
} } else super.onBackPressed();
else super.onBackPressed();
} }
protected void showFragment(Fragment f) { protected void showFragment(Fragment f) {
......
...@@ -8,15 +8,18 @@ import chat.rocket.android.helper.LogcatIfError; ...@@ -8,15 +8,18 @@ import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ServerConfig; import chat.rocket.android.model.ServerConfig;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts; import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
/**
* Entry-point for Rocket.Chat.Android application.
*/
public class MainActivity extends AbstractAuthedActivity { public class MainActivity extends AbstractAuthedActivity {
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
if (savedInstanceState==null) { if (savedInstanceState == null) {
RealmHelperBolts.executeTransaction(realm -> { RealmHelperBolts.executeTransaction(realm -> {
for(ServerConfig config: ServerConfig.queryActiveConnections(realm).findAll()) { for (ServerConfig config: ServerConfig.queryActiveConnections(realm).findAll()) {
config.setTokenVerified(false); config.setTokenVerified(false);
} }
return null; return null;
......
...@@ -13,7 +13,7 @@ import chat.rocket.android.R; ...@@ -13,7 +13,7 @@ import chat.rocket.android.R;
import chat.rocket.android.fragment.server_config.ConnectingToHostFragment; import chat.rocket.android.fragment.server_config.ConnectingToHostFragment;
import chat.rocket.android.fragment.server_config.InputHostnameFragment; import chat.rocket.android.fragment.server_config.InputHostnameFragment;
import chat.rocket.android.helper.TextUtils; import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerAuthProvider; import chat.rocket.android.model.MeteorLoginServiceConfiguration;
import chat.rocket.android.model.ServerConfig; import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.service.RocketChatService; import chat.rocket.android.service.RocketChatService;
import io.realm.Realm; import io.realm.Realm;
...@@ -21,6 +21,9 @@ import io.realm.RealmList; ...@@ -21,6 +21,9 @@ import io.realm.RealmList;
import io.realm.RealmQuery; import io.realm.RealmQuery;
import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver; import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver;
/**
* Activity for Login, Sign-up, and Connecting...
*/
public class ServerConfigActivity extends AbstractFragmentActivity { public class ServerConfigActivity extends AbstractFragmentActivity {
@Override @Override
...@@ -29,7 +32,8 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -29,7 +32,8 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
} }
private String mServerConfigId; private String mServerConfigId;
private RealmObjectObserver<ServerConfig> mServerConfigObserver = new RealmObjectObserver<ServerConfig>() { private RealmObjectObserver<ServerConfig> mServerConfigObserver =
new RealmObjectObserver<ServerConfig>() {
@Override @Override
protected RealmQuery<ServerConfig> query(Realm realm) { protected RealmQuery<ServerConfig> query(Realm realm) {
return realm.where(ServerConfig.class).equalTo("id", mServerConfigId); return realm.where(ServerConfig.class).equalTo("id", mServerConfigId);
...@@ -41,18 +45,20 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -41,18 +45,20 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
} }
}; };
/**
* Start the ServerConfigActivity with considering the priority of ServerConfig in the list.
*/
public static boolean launchFor(Context context, List<ServerConfig> configList) { public static boolean launchFor(Context context, List<ServerConfig> configList) {
for (ServerConfig config: configList) { for (ServerConfig config: configList) {
if (TextUtils.isEmpty(config.getHostname())) { if (TextUtils.isEmpty(config.getHostname())) {
return launchFor(context, config); return launchFor(context, config);
} } else if (!TextUtils.isEmpty(config.getConnectionError())) {
else if (!TextUtils.isEmpty(config.getConnectionError())) {
return launchFor(context, config); return launchFor(context, config);
} }
} }
for (ServerConfig config: configList) { for (ServerConfig config: configList) {
if (config.getProviders().isEmpty()) { if (config.getAuthProviders().isEmpty()) {
return launchFor(context, config); return launchFor(context, config);
} }
} }
...@@ -89,7 +95,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -89,7 +95,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = getIntent(); Intent intent = getIntent();
if (intent==null || intent.getExtras()==null) { if (intent == null || intent.getExtras() == null) {
finish(); finish();
return; return;
} }
...@@ -117,7 +123,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -117,7 +123,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
} }
private void onRenderServerConfig(ServerConfig config) { private void onRenderServerConfig(ServerConfig config) {
if (config==null) { if (config == null) {
finish(); finish();
return; return;
} }
...@@ -138,7 +144,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -138,7 +144,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
return; return;
} }
RealmList<ServerAuthProvider> providers = config.getProviders(); RealmList<MeteorLoginServiceConfiguration> providers = config.getAuthProviders();
if (!providers.isEmpty()) { if (!providers.isEmpty()) {
return; return;
...@@ -168,7 +174,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -168,7 +174,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
private void injectIdArgTo(Fragment f) { private void injectIdArgTo(Fragment f) {
Bundle args = f.getArguments(); Bundle args = f.getArguments();
if(args==null) args = new Bundle(); if (args == null) args = new Bundle();
args.putString("id", mServerConfigId); args.putString("id", mServerConfigId);
f.setArguments(args); f.setArguments(args);
} }
...@@ -177,8 +183,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity { ...@@ -177,8 +183,7 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
public void onBackPressed() { public void onBackPressed() {
if (ServerConfig.hasActiveConnection()) { if (ServerConfig.hasActiveConnection()) {
super.onBackPressed(); super.onBackPressed();
} } else {
else {
moveTaskToBack(true); moveTaskToBack(true);
} }
} }
......
...@@ -8,23 +8,28 @@ import android.view.LayoutInflater; ...@@ -8,23 +8,28 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
/**
* Fragment base class for this Application.
*/
public abstract class AbstractFragment extends Fragment { public abstract class AbstractFragment extends Fragment {
protected View mRootView; protected View mRootView;
protected abstract @LayoutRes int getLayout(); protected abstract @LayoutRes int getLayout();
protected abstract void onSetupView(); protected abstract void onSetupView();
@Nullable @Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @Override
mRootView = inflater.inflate(getLayout(), container,false); public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(getLayout(), container, false);
onSetupView(); onSetupView();
return mRootView; return mRootView;
} }
protected void finish() { protected void finish() {
if(getFragmentManager().getBackStackEntryCount()==0){ if (getFragmentManager().getBackStackEntryCount() == 0) {
getActivity().finish(); getActivity().finish();
} } else {
else {
getFragmentManager().popBackStack(); getFragmentManager().popBackStack();
} }
} }
......
...@@ -8,12 +8,13 @@ import chat.rocket.android.helper.TextUtils; ...@@ -8,12 +8,13 @@ import chat.rocket.android.helper.TextUtils;
abstract class AbstractServerConfigFragment extends AbstractFragment { abstract class AbstractServerConfigFragment extends AbstractFragment {
protected String mServerConfigId; protected String mServerConfigId;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Bundle args = getArguments(); Bundle args = getArguments();
if (args==null) { if (args == null) {
finish(); finish();
return; return;
} }
......
...@@ -2,6 +2,9 @@ package chat.rocket.android.fragment.server_config; ...@@ -2,6 +2,9 @@ package chat.rocket.android.fragment.server_config;
import chat.rocket.android.R; import chat.rocket.android.R;
/**
* Just showing "connecting..." screen.
*/
public class ConnectingToHostFragment extends AbstractServerConfigFragment { public class ConnectingToHostFragment extends AbstractServerConfigFragment {
@Override @Override
protected int getLayout() { protected int getLayout() {
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.fragment.server_config; ...@@ -2,7 +2,6 @@ package chat.rocket.android.fragment.server_config;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
...@@ -17,6 +16,9 @@ import io.realm.RealmQuery; ...@@ -17,6 +16,9 @@ import io.realm.RealmQuery;
import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver; import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts; import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
/**
* Input server host.
*/
public class InputHostnameFragment extends AbstractServerConfigFragment { public class InputHostnameFragment extends AbstractServerConfigFragment {
public InputHostnameFragment(){} public InputHostnameFragment(){}
...@@ -39,20 +41,25 @@ public class InputHostnameFragment extends AbstractServerConfigFragment { ...@@ -39,20 +41,25 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
@Override @Override
protected void onSetupView() { protected void onSetupView() {
mRootView.findViewById(R.id.btn_connect).setOnClickListener(v -> handleConnect());
mObserver.sub();
}
private void handleConnect() {
final TextView editor = (TextView) mRootView.findViewById(R.id.editor_hostname); final TextView editor = (TextView) mRootView.findViewById(R.id.editor_hostname);
final View btnConnect = mRootView.findViewById(R.id.btn_connect);
btnConnect.setOnClickListener(v -> { final String hostname = TextUtils.or(
final String hostname = TextUtils.or(TextUtils.or(editor.getText(), editor.getHint()), "").toString(); TextUtils.or(editor.getText(), editor.getHint()),
"").toString();
RealmHelperBolts RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject() .executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", mServerConfigId) .put("id", mServerConfigId)
.put("hostname", hostname) .put("hostname", hostname)
.put("connectionError", JSONObject.NULL))) .put("connectionError", JSONObject.NULL)))
.continueWith(new LogcatIfError()); .continueWith(new LogcatIfError());
});
mObserver.sub();
} }
@Override @Override
...@@ -82,6 +89,7 @@ public class InputHostnameFragment extends AbstractServerConfigFragment { ...@@ -82,6 +89,7 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
private void onRenderServerConfig(ServerConfig config) { private void onRenderServerConfig(ServerConfig config) {
final TextView editor = (TextView) mRootView.findViewById(R.id.editor_hostname); final TextView editor = (TextView) mRootView.findViewById(R.id.editor_hostname);
if (!TextUtils.isEmpty(config.getHostname())) editor.setText(config.getHostname()); if (!TextUtils.isEmpty(config.getHostname())) editor.setText(config.getHostname());
if (!TextUtils.isEmpty(config.getConnectionError())) { if (!TextUtils.isEmpty(config.getConnectionError())) {
clearConnectionErrorAndHostname(); clearConnectionErrorAndHostname();
...@@ -91,7 +99,8 @@ public class InputHostnameFragment extends AbstractServerConfigFragment { ...@@ -91,7 +99,8 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
private void clearConnectionErrorAndHostname() { private void clearConnectionErrorAndHostname() {
RealmHelperBolts RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject() .executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", mServerConfigId) .put("id", mServerConfigId)
.put("hostname", JSONObject.NULL) .put("hostname", JSONObject.NULL)
.put("connectionError", JSONObject.NULL))) .put("connectionError", JSONObject.NULL)))
......
...@@ -4,6 +4,9 @@ import bolts.Continuation; ...@@ -4,6 +4,9 @@ import bolts.Continuation;
import bolts.Task; import bolts.Task;
import timber.log.Timber; import timber.log.Timber;
/**
* Bolts-Task continuation for just logging if error occurred.
*/
public class LogcatIfError implements Continuation { public class LogcatIfError implements Continuation {
@Override @Override
public Object then(Task task) throws Exception { public Object then(Task task) throws Exception {
......
...@@ -7,11 +7,17 @@ import java.util.concurrent.TimeUnit; ...@@ -7,11 +7,17 @@ import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
/**
* Helper class for OkHttp client.
*/
public class OkHttpHelper { public class OkHttpHelper {
private static OkHttpClient sHttpClientForWS; private static OkHttpClient sHttpClientForWS;
public static OkHttpClient getClientForWebSocket() {
if (sHttpClientForWS==null) { /**
* acquire OkHttpClient instance for WebSocket connection.
*/
public static OkHttpClient getClientForWebSocket() {
if (sHttpClientForWS == null) {
sHttpClientForWS = new OkHttpClient.Builder() sHttpClientForWS = new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.NANOSECONDS) .readTimeout(0, TimeUnit.NANOSECONDS)
.addNetworkInterceptor(new StethoInterceptor()) .addNetworkInterceptor(new StethoInterceptor())
......
package chat.rocket.android.helper; package chat.rocket.android.helper;
/**
* Interface that just have onBackPressed().
*/
public interface OnBackPressListener { public interface OnBackPressListener {
/**
* onBackPressed
*
* @return whether back is handled or not.
*/
boolean onBackPressed(); boolean onBackPressed();
} }
package chat.rocket.android.helper; package chat.rocket.android.helper;
/**
* Text Utility class like android.text.TextUtils.
*/
public class TextUtils { public class TextUtils {
/**
* Returns true if the string is null or 0-length.
* @param str the string to be examined
* @return true if str is null or zero length
*/
public static boolean isEmpty(CharSequence str) { public static boolean isEmpty(CharSequence str) {
// same definition as android.text.TextUtils#isEmpty(). // same definition as android.text.TextUtils#isEmpty().
return str == null || str.length() == 0; return str == null || str.length() == 0;
} }
/**
* Returns str if it is not empty; otherwise defaultValue is returned.
*/
public static CharSequence or(CharSequence str, CharSequence defaultValue) { public static CharSequence or(CharSequence str, CharSequence defaultValue) {
if (isEmpty(str)) return defaultValue; if (isEmpty(str)) return defaultValue;
return str; return str;
......
package chat.rocket.android.model.doc; package chat.rocket.android.model;
import io.realm.RealmObject; import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey; import io.realm.annotations.PrimaryKey;
/**
* subscription model for "meteor_accounts_loginServiceConfiguration"
*/
public class MeteorLoginServiceConfiguration extends RealmObject { public class MeteorLoginServiceConfiguration extends RealmObject {
@PrimaryKey @PrimaryKey
private String id; private String id;
private String service; private String service;
private String consumerKey; //for Twitter private String consumerKey; //for Twitter
private String appId;//for Facebook private String appId; //for Facebook
private String clientId;//for other auth providers private String clientId; //for other auth providers
} }
package chat.rocket.android.model;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class ServerAuthProvider extends RealmObject {
@PrimaryKey
private String name; //email, twitter, github, ...
}
...@@ -12,6 +12,9 @@ import io.realm.annotations.PrimaryKey; ...@@ -12,6 +12,9 @@ import io.realm.annotations.PrimaryKey;
import jp.co.crowdworks.realm_java_helpers.RealmHelper; import jp.co.crowdworks.realm_java_helpers.RealmHelper;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts; import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
/**
* Server configuration
*/
public class ServerConfig extends RealmObject { public class ServerConfig extends RealmObject {
@PrimaryKey @PrimaryKey
private String id; private String id;
...@@ -19,7 +22,7 @@ public class ServerConfig extends RealmObject { ...@@ -19,7 +22,7 @@ public class ServerConfig extends RealmObject {
private String connectionError; private String connectionError;
private String token; private String token;
private boolean tokenVerified; private boolean tokenVerified;
private RealmList<ServerAuthProvider> providers; private RealmList<MeteorLoginServiceConfiguration> authProviders;
private String selectedProviderName; private String selectedProviderName;
public String getId() { public String getId() {
...@@ -62,12 +65,12 @@ public class ServerConfig extends RealmObject { ...@@ -62,12 +65,12 @@ public class ServerConfig extends RealmObject {
this.tokenVerified = tokenVerified; this.tokenVerified = tokenVerified;
} }
public RealmList<ServerAuthProvider> getProviders() { public RealmList<MeteorLoginServiceConfiguration> getAuthProviders() {
return providers; return authProviders;
} }
public void setProviders(RealmList<ServerAuthProvider> providers) { public void setAuthProviders(RealmList<MeteorLoginServiceConfiguration> authProviders) {
this.providers = providers; this.authProviders = authProviders;
} }
public String getSelectedProviderName() { public String getSelectedProviderName() {
...@@ -98,7 +101,8 @@ public class ServerConfig extends RealmObject { ...@@ -98,7 +101,8 @@ public class ServerConfig extends RealmObject {
@DebugLog @DebugLog
public static void logError(String id, Exception e) { public static void logError(String id, Exception e) {
RealmHelperBolts RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject() .executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", id) .put("id", id)
.put("connectionError", e.getMessage()))) .put("connectionError", e.getMessage())))
.continueWith(new LogcatIfError()); .continueWith(new LogcatIfError());
......
package chat.rocket.android.service; package chat.rocket.android.service;
/**
* interface for observer and ddp_subscription
*/
public interface Registerable { public interface Registerable {
/**
* register
*/
void register(); void register();
/**
* keepalive
*/
void keepalive(); void keepalive();
/**
* unregister
*/
void unregister(); void unregister();
} }
...@@ -17,18 +17,28 @@ import io.realm.Realm; ...@@ -17,18 +17,28 @@ import io.realm.Realm;
import io.realm.RealmResults; import io.realm.RealmResults;
import jp.co.crowdworks.realm_java_helpers.RealmListObserver; import jp.co.crowdworks.realm_java_helpers.RealmListObserver;
/**
* Background service for Rocket.Chat.Application class.
*/
public class RocketChatService extends Service { public class RocketChatService extends Service {
/**
* ensure RocketChatService alive.
*/
public static void keepalive(Context context) { public static void keepalive(Context context) {
context.startService(new Intent(context, RocketChatService.class)); context.startService(new Intent(context, RocketChatService.class));
} }
/**
* force stop RocketChatService.
*/
public static void kill(Context context) { public static void kill(Context context) {
context.stopService(new Intent(context, RocketChatService.class)); context.stopService(new Intent(context, RocketChatService.class));
} }
private HashMap<String, RocketChatWebSocketThread> mWebSocketThreads; private HashMap<String, RocketChatWebSocketThread> mWebSocketThreads;
private RealmListObserver<ServerConfig> mConnectionRequiredServerConfigObserver = new RealmListObserver<ServerConfig>() { private RealmListObserver<ServerConfig> mConnectionRequiredServerConfigObserver =
new RealmListObserver<ServerConfig>() {
@Override @Override
protected RealmResults<ServerConfig> queryItems(Realm realm) { protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class) return realm.where(ServerConfig.class)
...@@ -56,12 +66,14 @@ public class RocketChatService extends Service { ...@@ -56,12 +66,14 @@ public class RocketChatService extends Service {
} }
private void syncWebSocketThreadsWith(List<ServerConfig> configList) { private void syncWebSocketThreadsWith(List<ServerConfig> configList) {
final Iterator<Map.Entry<String, RocketChatWebSocketThread>> it = mWebSocketThreads.entrySet().iterator(); final Iterator<Map.Entry<String, RocketChatWebSocketThread>> it =
while(it.hasNext()) { mWebSocketThreads.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, RocketChatWebSocketThread> e = it.next(); Map.Entry<String, RocketChatWebSocketThread> e = it.next();
String id = e.getKey(); String id = e.getKey();
boolean found = false; boolean found = false;
for(ServerConfig config: configList) { for (ServerConfig config: configList) {
if (id.equals(config.getId())) { if (id.equals(config.getId())) {
found = true; found = true;
break; break;
...@@ -73,7 +85,7 @@ public class RocketChatService extends Service { ...@@ -73,7 +85,7 @@ public class RocketChatService extends Service {
} }
} }
for(ServerConfig config: configList) { for (ServerConfig config: configList) {
findOrCreateWebSocketThread(config).onSuccess(task -> { findOrCreateWebSocketThread(config).onSuccess(task -> {
RocketChatWebSocketThread thread = task.getResult(); RocketChatWebSocketThread thread = task.getResult();
thread.syncStateWith(config); thread.syncStateWith(config);
...@@ -86,9 +98,9 @@ public class RocketChatService extends Service { ...@@ -86,9 +98,9 @@ public class RocketChatService extends Service {
final String id = config.getId(); final String id = config.getId();
if (mWebSocketThreads.containsKey(id)) { if (mWebSocketThreads.containsKey(id)) {
return Task.forResult(mWebSocketThreads.get(id)); return Task.forResult(mWebSocketThreads.get(id));
} } else {
else { return RocketChatWebSocketThread.getStarted(getApplicationContext(), config)
return RocketChatWebSocketThread.getStarted(getApplicationContext(), config).onSuccessTask(task -> { .onSuccessTask(task -> {
mWebSocketThreads.put(id, task.getResult()); mWebSocketThreads.put(id, task.getResult());
return task; return task;
}); });
......
...@@ -12,15 +12,16 @@ import bolts.Task; ...@@ -12,15 +12,16 @@ import bolts.Task;
import bolts.TaskCompletionSource; import bolts.TaskCompletionSource;
import chat.rocket.android.helper.TextUtils; import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig; import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.service.ddp_subscription.LoginServiceConfigurationSubscriber; import chat.rocket.android.service.ddp_subscriber.LoginServiceConfigurationSubscriber;
import chat.rocket.android.ws.RocketChatWebSocketAPI; import chat.rocket.android.ws.RocketChatWebSocketAPI;
import chat.rocket.android_ddp.DDPClient; import chat.rocket.android_ddp.DDPClient;
import hugo.weaving.DebugLog; import hugo.weaving.DebugLog;
import jp.co.crowdworks.realm_java_helpers.RealmHelper; import jp.co.crowdworks.realm_java_helpers.RealmHelper;
import timber.log.Timber; import timber.log.Timber;
import static android.content.ContentValues.TAG; /**
* Thread for handling WebSocket connection.
*/
public class RocketChatWebSocketThread extends HandlerThread { public class RocketChatWebSocketThread extends HandlerThread {
private final Context mAppContext; private final Context mAppContext;
private final String mServerConfigId; private final String mServerConfigId;
...@@ -29,13 +30,17 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -29,13 +30,17 @@ public class RocketChatWebSocketThread extends HandlerThread {
private boolean mListenersRegistered; private boolean mListenersRegistered;
private RocketChatWebSocketThread(Context appContext, String id) { private RocketChatWebSocketThread(Context appContext, String id) {
super("RC_thread_"+id); super("RC_thread_" + id);
mServerConfigId = id; mServerConfigId = id;
mAppContext = appContext; mAppContext = appContext;
} }
/**
* create new Thread.
*/
@DebugLog @DebugLog
public static Task<RocketChatWebSocketThread> getStarted(Context appContext, ServerConfig config) { public static Task<RocketChatWebSocketThread> getStarted(Context appContext,
ServerConfig config) {
TaskCompletionSource<RocketChatWebSocketThread> task = new TaskCompletionSource<>(); TaskCompletionSource<RocketChatWebSocketThread> task = new TaskCompletionSource<>();
new RocketChatWebSocketThread(appContext, config.getId()){ new RocketChatWebSocketThread(appContext, config.getId()){
@Override @Override
...@@ -43,8 +48,7 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -43,8 +48,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
try { try {
super.onLooperPrepared(); super.onLooperPrepared();
task.setResult(this); task.setResult(this);
} } catch (Exception e) {
catch (Exception e) {
task.setError(e); task.setError(e);
} }
} }
...@@ -52,6 +56,9 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -52,6 +56,9 @@ public class RocketChatWebSocketThread extends HandlerThread {
return task.getTask(); return task.getTask();
} }
/**
* terminate the thread
*/
@DebugLog @DebugLog
public static void terminate(RocketChatWebSocketThread t) { public static void terminate(RocketChatWebSocketThread t) {
t.quit(); t.quit();
...@@ -60,21 +67,24 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -60,21 +67,24 @@ public class RocketChatWebSocketThread extends HandlerThread {
private Task<Void> ensureConnection() { private Task<Void> ensureConnection() {
if (mWebSocketAPI == null || !mWebSocketAPI.isConnected()) { if (mWebSocketAPI == null || !mWebSocketAPI.isConnected()) {
return registerListeners(); return registerListeners();
} else {
return Task.forResult(null);
} }
else return Task.forResult(null);
} }
/**
* synchronize the state of the thread with ServerConfig.
*/
@DebugLog @DebugLog
public void syncStateWith(ServerConfig config) { public void syncStateWith(ServerConfig config) {
if (config == null || TextUtils.isEmpty(config.getHostname()) || !TextUtils.isEmpty(config.getConnectionError())) { if (config == null
|| TextUtils.isEmpty(config.getHostname())
|| !TextUtils.isEmpty(config.getConnectionError())) {
quit(); quit();
} } else {
else {
ensureConnection() ensureConnection()
.continueWith(task -> { .continueWith(task -> {
new Handler(getLooper()).post(() -> { new Handler(getLooper()).post(this::keepaliveListeners);
keepaliveListeners();
});
return null; return null;
}); });
} }
...@@ -115,14 +125,18 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -115,14 +125,18 @@ public class RocketChatWebSocketThread extends HandlerThread {
private final ArrayList<Registerable> mListeners = new ArrayList<>(); private final ArrayList<Registerable> mListeners = new ArrayList<>();
private void prepareWebSocket() { private void prepareWebSocket() {
ServerConfig config = RealmHelper.executeTransactionForRead(realm -> realm.where(ServerConfig.class).equalTo("id", mServerConfigId).findFirst()); ServerConfig config = RealmHelper.executeTransactionForRead(realm ->
realm.where(ServerConfig.class)
.equalTo("id", mServerConfigId)
.findFirst());
if (mWebSocketAPI == null || !mWebSocketAPI.isConnected()) { if (mWebSocketAPI == null || !mWebSocketAPI.isConnected()) {
mWebSocketAPI = RocketChatWebSocketAPI.create(config.getHostname()); mWebSocketAPI = RocketChatWebSocketAPI.create(config.getHostname());
} }
} }
@DebugLog @DebugLog
private Task<Void> registerListeners(){ private Task<Void> registerListeners() {
if (mSocketExists) return Task.forResult(null); if (mSocketExists) return Task.forResult(null);
mSocketExists = true; mSocketExists = true;
...@@ -140,7 +154,7 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -140,7 +154,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
// just for debugging. // just for debugging.
client.getSubscriptionCallback().subscribe(event -> { client.getSubscriptionCallback().subscribe(event -> {
Timber.d(TAG, "Callback [DEBUG] < " + event); Timber.d("Callback [DEBUG] < " + event);
}); });
return null; return null;
...@@ -157,35 +171,36 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -157,35 +171,36 @@ public class RocketChatWebSocketThread extends HandlerThread {
if (mListenersRegistered) return; if (mListenersRegistered) return;
mListenersRegistered = true; mListenersRegistered = true;
for(Class clazz: REGISTERABLE_CLASSES){ for (Class clazz: REGISTERABLE_CLASSES) {
try { try {
Constructor ctor = clazz.getConstructor(Context.class, RocketChatWebSocketAPI.class); Constructor ctor = clazz.getConstructor(
Context.class, RocketChatWebSocketAPI.class);
Object obj = ctor.newInstance(mAppContext, mWebSocketAPI); Object obj = ctor.newInstance(mAppContext, mWebSocketAPI);
if(obj instanceof Registerable) { if (obj instanceof Registerable) {
Registerable l = (Registerable) obj; Registerable l = (Registerable) obj;
l.register(); l.register();
mListeners.add(l); mListeners.add(l);
} }
} catch (Exception e) { } catch (Exception e) {
Timber.w(e); Timber.w(e, "Failed to register listeners!!");
} }
} }
} }
//@DebugLog //@DebugLog
private void keepaliveListeners(){ private void keepaliveListeners() {
if (!mSocketExists || !mListenersRegistered) return; if (!mSocketExists || !mListenersRegistered) return;
for (Registerable l : mListeners) l.keepalive(); for (Registerable l : mListeners) l.keepalive();
} }
//@DebugLog //@DebugLog
private void unregisterListeners(){ private void unregisterListeners() {
if (!mSocketExists || !mListenersRegistered) return; if (!mSocketExists || !mListenersRegistered) return;
Iterator<Registerable> it = mListeners.iterator(); Iterator<Registerable> it = mListeners.iterator();
while(it.hasNext()){ while (it.hasNext()) {
Registerable l = it.next(); Registerable l = it.next();
l.unregister(); l.unregister();
it.remove(); it.remove();
......
package chat.rocket.android.service.ddp_subscription; package chat.rocket.android.service.ddp_subscriber;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -24,7 +24,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -24,7 +24,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
private String mID; private String mID;
private Subscription mSubscription; private Subscription mSubscription;
public AbstractDDPDocEventSubscriber(Context context, RocketChatWebSocketAPI api) { protected AbstractDDPDocEventSubscriber(Context context, RocketChatWebSocketAPI api) {
mContext = context; mContext = context;
mAPI = api; mAPI = api;
} }
...@@ -32,7 +32,9 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -32,7 +32,9 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
protected abstract String getSubscriptionName(); protected abstract String getSubscriptionName();
protected abstract String getSubscriptionCallbackName(); protected abstract String getSubscriptionCallbackName();
protected abstract Class<? extends RealmObject> getModelClass(); protected abstract Class<? extends RealmObject> getModelClass();
protected JSONObject customizeFieldJSON(JSONObject json) { return json; } protected JSONObject customizeFieldJSON(JSONObject json) {
return json;
}
@Override @Override
public void register() { public void register() {
...@@ -41,7 +43,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -41,7 +43,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
return null; return null;
}).continueWith(task -> { }).continueWith(task -> {
if (task.isFaulted()) { if (task.isFaulted()) {
Timber.w(task.getError()); Timber.w(task.getError(), "DDP subscription failed.");
} }
return null; return null;
}); });
...@@ -57,9 +59,9 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -57,9 +59,9 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
private void registerSubscriptionCallback() { private void registerSubscriptionCallback() {
mSubscription = mAPI.getSubscriptionCallback() mSubscription = mAPI.getSubscriptionCallback()
.filter(event -> event instanceof DDPSubscription.DocEvent .filter(event -> event instanceof DDPSubscription.DocEvent)
&& getSubscriptionCallbackName().equals(((DDPSubscription.DocEvent) event).collection))
.cast(DDPSubscription.DocEvent.class) .cast(DDPSubscription.DocEvent.class)
.filter(event -> getSubscriptionCallbackName().equals(event.collection))
.subscribe(docEvent -> { .subscribe(docEvent -> {
try { try {
if (docEvent instanceof DDPSubscription.Added.Before) { if (docEvent instanceof DDPSubscription.Added.Before) {
...@@ -74,7 +76,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -74,7 +76,7 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
//ignore movedBefore //ignore movedBefore
} }
} catch (Exception e) { } catch (Exception e) {
Timber.w(e); Timber.w(e, "failed to handle subscription callback");
} }
}); });
} }
...@@ -102,23 +104,25 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -102,23 +104,25 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
private void mergeJSON(JSONObject target, JSONObject src) throws JSONException { private void mergeJSON(JSONObject target, JSONObject src) throws JSONException {
Iterator<String> it = src.keys(); Iterator<String> it = src.keys();
while(it.hasNext()) { while (it.hasNext()) {
String key = it.next(); String key = it.next();
target.put(key, src.get(key)); target.put(key, src.get(key));
} }
} }
private void onDocumentAdded(Realm realm, DDPSubscription.Added docEvent) throws JSONException { private void onDocumentAdded(Realm realm, DDPSubscription.Added docEvent)
throws JSONException {
//executed in RealmTransaction //executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID); JSONObject json = new JSONObject().put("id", docEvent.docID);
mergeJSON(json, docEvent.fields); mergeJSON(json, docEvent.fields);
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json)); realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json));
} }
private void onDocumentChanged(Realm realm, DDPSubscription.Changed docEvent) throws JSONException { private void onDocumentChanged(Realm realm, DDPSubscription.Changed docEvent)
throws JSONException {
//executed in RealmTransaction //executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID); JSONObject json = new JSONObject().put("id", docEvent.docID);
for (int i=0; i<docEvent.cleared.length(); i++) { for (int i = 0; i < docEvent.cleared.length(); i++) {
String fieldToDelete = docEvent.cleared.getString(i); String fieldToDelete = docEvent.cleared.getString(i);
json.remove(fieldToDelete); json.remove(fieldToDelete);
} }
...@@ -126,7 +130,8 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable { ...@@ -126,7 +130,8 @@ abstract class AbstractDDPDocEventSubscriber implements Registerable {
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json)); realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json));
} }
private void onDocumentRemoved(Realm realm, DDPSubscription.Removed docEvent) throws JSONException { private void onDocumentRemoved(Realm realm, DDPSubscription.Removed docEvent)
throws JSONException {
//executed in RealmTransaction //executed in RealmTransaction
realm.where(getModelClass()).equalTo("id", docEvent.docID).findAll().deleteAllFromRealm(); realm.where(getModelClass()).equalTo("id", docEvent.docID).findAll().deleteAllFromRealm();
} }
......
package chat.rocket.android.service.ddp_subscription; package chat.rocket.android.service.ddp_subscriber;
import android.content.Context; import android.content.Context;
import chat.rocket.android.model.doc.MeteorLoginServiceConfiguration; import chat.rocket.android.model.MeteorLoginServiceConfiguration;
import chat.rocket.android.ws.RocketChatWebSocketAPI; import chat.rocket.android.ws.RocketChatWebSocketAPI;
import io.realm.RealmObject; import io.realm.RealmObject;
/**
* meteor.loginServiceConfiguration subscriber
*/
public class LoginServiceConfigurationSubscriber extends AbstractDDPDocEventSubscriber { public class LoginServiceConfigurationSubscriber extends AbstractDDPDocEventSubscriber {
public LoginServiceConfigurationSubscriber(Context context, RocketChatWebSocketAPI api) { public LoginServiceConfigurationSubscriber(Context context, RocketChatWebSocketAPI api) {
super(context, api); super(context, api);
......
...@@ -7,12 +7,13 @@ import chat.rocket.android.ws.RocketChatWebSocketAPI; ...@@ -7,12 +7,13 @@ import chat.rocket.android.ws.RocketChatWebSocketAPI;
import io.realm.RealmObject; import io.realm.RealmObject;
import jp.co.crowdworks.realm_java_helpers.RealmListObserver; import jp.co.crowdworks.realm_java_helpers.RealmListObserver;
abstract class AbstractModelObserver<T extends RealmObject> extends RealmListObserver<T> implements Registerable { abstract class AbstractModelObserver<T extends RealmObject>
extends RealmListObserver<T> implements Registerable {
protected final Context mContext; protected final Context mContext;
protected final RocketChatWebSocketAPI mAPI; protected final RocketChatWebSocketAPI mAPI;
public AbstractModelObserver(Context context, RocketChatWebSocketAPI api) { protected AbstractModelObserver(Context context, RocketChatWebSocketAPI api) {
mContext = context; mContext = context;
mAPI = api; mAPI = api;
} }
......
...@@ -9,26 +9,32 @@ abstract class AbstractCustomFontTextView extends AppCompatTextView { ...@@ -9,26 +9,32 @@ abstract class AbstractCustomFontTextView extends AppCompatTextView {
protected abstract String getFont(); protected abstract String getFont();
//CHECKSTYLE:OFF RedundantModifier
public AbstractCustomFontTextView(Context context, AttributeSet attrs, int defStyle) { public AbstractCustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
init(); init();
} }
//CHECKSTYLE:ON RedundantModifier
//CHECKSTYLE:OFF RedundantModifier
public AbstractCustomFontTextView(Context context, AttributeSet attrs) { public AbstractCustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init(); init();
} }
//CHECKSTYLE:ON RedundantModifier
//CHECKSTYLE:OFF RedundantModifier
public AbstractCustomFontTextView(Context context) { public AbstractCustomFontTextView(Context context) {
super(context); super(context);
init(); init();
} }
//CHECKSTYLE:ON RedundantModifier
private void init() { private void init() {
String font = getFont(); String font = getFont();
if (font!=null) { if (font != null) {
Typeface tf = TypefaceHelper.getTypeface(getContext(), font); Typeface tf = TypefaceHelper.getTypeface(getContext(), font);
if (tf!=null) setTypeface(tf); if (tf != null) setTypeface(tf);
} }
} }
} }
...@@ -3,6 +3,9 @@ package chat.rocket.android.view; ...@@ -3,6 +3,9 @@ package chat.rocket.android.view;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
/**
* TextView with font-awesome
*/
public class FontAwesomeTextView extends AbstractCustomFontTextView { public class FontAwesomeTextView extends AbstractCustomFontTextView {
public FontAwesomeTextView(Context context, AttributeSet attrs, int defStyle) { public FontAwesomeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
......
...@@ -3,6 +3,9 @@ package chat.rocket.android.view; ...@@ -3,6 +3,9 @@ package chat.rocket.android.view;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
/**
* TextView with fontello
*/
public class FontelloTextView extends AbstractCustomFontTextView { public class FontelloTextView extends AbstractCustomFontTextView {
public FontelloTextView(Context context, AttributeSet attrs, int defStyle) { public FontelloTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
......
...@@ -6,26 +6,32 @@ import android.util.Log; ...@@ -6,26 +6,32 @@ import android.util.Log;
import java.util.Hashtable; import java.util.Hashtable;
// ref:https://code.google.com/p/android/issues/detail?id=9904#c7 /**
* Helper for reading typeface.
* ref:https://code.google.com/p/android/issues/detail?id=9904#c7
*/
public class TypefaceHelper { public class TypefaceHelper {
private static final String TAG = TypefaceHelper.class.getName(); private static final String TAG = TypefaceHelper.class.getName();
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>(); private static final Hashtable<String, Typeface> CACHE = new Hashtable<String, Typeface>();
/**
* read font in assets directory.
*/
public static Typeface getTypeface(Context c, String assetPath) { public static Typeface getTypeface(Context c, String assetPath) {
synchronized (cache) { synchronized (CACHE) {
if (!cache.containsKey(assetPath)) { if (!CACHE.containsKey(assetPath)) {
try { try {
Typeface t = Typeface.createFromAsset(c.getAssets(), Typeface t = Typeface.createFromAsset(c.getAssets(),
assetPath); assetPath);
cache.put(assetPath, t); CACHE.put(assetPath, t);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Could not get typeface '" + assetPath Log.e(TAG, "Could not get typeface '" + assetPath
+ "' because " + e.getMessage()); + "' because " + e.getMessage());
return null; return null;
} }
} }
return cache.get(assetPath); return CACHE.get(assetPath);
} }
} }
} }
...@@ -16,7 +16,9 @@ import java.util.ArrayList; ...@@ -16,7 +16,9 @@ import java.util.ArrayList;
import chat.rocket.android.R; import chat.rocket.android.R;
/**
* View for indicating "waiting for connection ..." and so on.
*/
public class WaitingView extends LinearLayout { public class WaitingView extends LinearLayout {
private ArrayList<View> mDots; private ArrayList<View> mDots;
...@@ -56,7 +58,7 @@ public class WaitingView extends LinearLayout { ...@@ -56,7 +58,7 @@ public class WaitingView extends LinearLayout {
mDots = new ArrayList<>(); mDots = new ArrayList<>();
setOrientation(HORIZONTAL); setOrientation(HORIZONTAL);
for (int i=0; i<count; i++) addDot(context, size); for (int i = 0; i < count; i++) addDot(context, size);
addOnAttachStateChangeListener(new OnAttachStateChangeListener() { addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override @Override
...@@ -73,7 +75,7 @@ public class WaitingView extends LinearLayout { ...@@ -73,7 +75,7 @@ public class WaitingView extends LinearLayout {
private void addDot(Context context, int size) { private void addDot(Context context, int size) {
FrameLayout f = new FrameLayout(context); FrameLayout f = new FrameLayout(context);
f.setLayoutParams(new LinearLayoutCompat.LayoutParams(size*3/2, size*3/2)); f.setLayoutParams(new LinearLayoutCompat.LayoutParams(size * 3 / 2, size * 3 / 2));
ImageView dot = new ImageView(context); ImageView dot = new ImageView(context);
dot.setImageResource(R.drawable.white_circle); dot.setImageResource(R.drawable.white_circle);
dot.setLayoutParams(new FrameLayout.LayoutParams(size, size, Gravity.CENTER)); dot.setLayoutParams(new FrameLayout.LayoutParams(size, size, Gravity.CENTER));
...@@ -83,12 +85,15 @@ public class WaitingView extends LinearLayout { ...@@ -83,12 +85,15 @@ public class WaitingView extends LinearLayout {
} }
private void start() { private void start() {
for(int i=0; i<mDots.size(); i++) { for (int i = 0; i < mDots.size(); i++) {
animateDot(mDots.get(i), 160*i, 480, 480); animateDot(mDots.get(i), 160 * i, 480, 480);
} }
} }
private void animateDot(final View dot, final long startDelay, final long duration, final long interval) { private void animateDot(final View dot,
final long startDelay,
final long duration,
final long interval) {
dot.setScaleX(0); dot.setScaleX(0);
dot.setScaleY(0); dot.setScaleY(0);
dot.animate() dot.animate()
...@@ -109,7 +114,7 @@ public class WaitingView extends LinearLayout { ...@@ -109,7 +114,7 @@ public class WaitingView extends LinearLayout {
} }
private void cancel() { private void cancel() {
for(View dot: mDots) { for (View dot: mDots) {
dot.clearAnimation(); dot.clearAnimation();
} }
} }
......
...@@ -11,6 +11,9 @@ import chat.rocket.android_ddp.DDPClientCallback; ...@@ -11,6 +11,9 @@ import chat.rocket.android_ddp.DDPClientCallback;
import chat.rocket.android_ddp.DDPSubscription; import chat.rocket.android_ddp.DDPSubscription;
import rx.Observable; import rx.Observable;
/**
* API for several POST actions.
*/
public class RocketChatWebSocketAPI { public class RocketChatWebSocketAPI {
private final DDPClient mDDPClient; private final DDPClient mDDPClient;
private final String mHostName; private final String mHostName;
...@@ -20,31 +23,52 @@ public class RocketChatWebSocketAPI { ...@@ -20,31 +23,52 @@ public class RocketChatWebSocketAPI {
mHostName = hostname; mHostName = hostname;
} }
/**
* create new API client instance.
*/
public static RocketChatWebSocketAPI create(String hostname) { public static RocketChatWebSocketAPI create(String hostname) {
return new RocketChatWebSocketAPI(hostname); return new RocketChatWebSocketAPI(hostname);
} }
/**
* Connect to WebSocket server with DDP client.
*/
public Task<DDPClientCallback.Connect> connect() { public Task<DDPClientCallback.Connect> connect() {
return mDDPClient.connect("wss://" + mHostName + "/websocket"); return mDDPClient.connect("wss://" + mHostName + "/websocket");
} }
/**
* Returns whether DDP client is connected to WebSocket server.
*/
public boolean isConnected() { public boolean isConnected() {
return mDDPClient.isConnected(); return mDDPClient.isConnected();
} }
/**
* close connection.
*/
public void close() { public void close() {
mDDPClient.close(); mDDPClient.close();
} }
/**
* Subscribe with DDP client.
*/
public Task<DDPSubscription.Ready> subscribe(final String name, JSONArray param) { public Task<DDPSubscription.Ready> subscribe(final String name, JSONArray param) {
return mDDPClient.sub(UUID.randomUUID().toString(), name, param); return mDDPClient.sub(UUID.randomUUID().toString(), name, param);
} }
/**
* Unsubscribe with DDP client.
*/
public Task<DDPSubscription.NoSub> unsubscribe(final String id) { public Task<DDPSubscription.NoSub> unsubscribe(final String id) {
return mDDPClient.unsub(id); return mDDPClient.unsub(id);
} }
/**
* Returns Observable for handling DDP subscription.
*/
public Observable<DDPSubscription.Event> getSubscriptionCallback() { public Observable<DDPSubscription.Event> getSubscriptionCallback() {
return mDDPClient.getSubscriptionCallback(); return mDDPClient.getSubscriptionCallback();
} }
......
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