Commit d4d4cd46 authored by Yusuke Iwaki's avatar Yusuke Iwaki Committed by GitHub

Merge pull request #42 from RocketChat/fix_style_and_rules

Fix style and rules
parents d6e44491 3b4396da
......@@ -5,52 +5,56 @@ apply plugin: 'com.jakewharton.hugo'
apply from: '../config/quality/quality.gradle'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "chat.rocket.android"
minSdkVersion 17
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "chat.rocket.android"
minSdkVersion 17
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
//avoiding okio error: https://github.com/square/okhttp/issues/896
lintConfig file("lint.xml")
}
}
repositories {
mavenCentral()
maven { url 'https://github.com/YusukeIwaki/realm-java-helpers/raw/master/repo' }
maven { url 'https://github.com/uPhyca/stetho-realm/raw/master/maven-repo' }
maven { url 'https://github.com/RocketChat/Android-DDP/raw/master/repository' }
mavenCentral()
maven { url 'https://github.com/YusukeIwaki/realm-java-helpers/raw/master/repo' }
maven { url 'https://github.com/uPhyca/stetho-realm/raw/master/maven-repo' }
maven { url 'https://github.com/RocketChat/Android-DDP/raw/master/repository' }
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.android.support:design:25.0.0'
compile 'jp.co.crowdworks:realm-java-helpers:0.0.7'
compile 'jp.co.crowdworks:realm-java-helpers-bolts:0.0.7'
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.android.support:design:25.0.0'
compile 'jp.co.crowdworks:realm-java-helpers:0.0.7'
compile 'jp.co.crowdworks:realm-java-helpers-bolts:0.0.7'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.facebook.stetho:stetho:1.4.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
compile 'com.uphyca:stetho_realm:2.0.0'
compile 'com.facebook.stetho:stetho:1.4.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
compile 'com.uphyca:stetho_realm:2.0.0'
compile 'chat.rocket:android-ddp:0.0.5'
compile 'chat.rocket:android-ddp:0.0.5'
compile 'com.jakewharton.timber:timber:4.3.1'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
compile 'com.jakewharton.timber:timber:4.3.1'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
}
<lint>
<issue id="InvalidPackage">
<ignore regexp="okio.*jar"/>
</issue>
</lint>
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name=".RocketChatApplication">
<application
android:name=".RocketChatApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activity.MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<activity android:name=".activity.ServerConfigActivity"
android:windowSoftInputMode="adjustResize"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".service.RocketChatService"/>
</application>
<activity
android:name=".activity.ServerConfigActivity"
android:windowSoftInputMode="adjustResize"/>
<service android:name=".service.RocketChatService"/>
</application>
</manifest>
......@@ -2,14 +2,19 @@ package chat.rocket.android;
import android.content.Context;
import android.content.Intent;
import chat.rocket.android.activity.ServerConfigActivity;
/**
* utility class for launching Activity.
*/
public class LaunchUtil {
public static void showServerConfigActivity(Context context, String id) {
Intent intent = new Intent(context, ServerConfigActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("id", id);
context.startActivity(intent);
}
/**
* launch ServerConfigActivity with proper flags.
*/
public static void showServerConfigActivity(Context context, String serverCondigId) {
Intent intent = new Intent(context, ServerConfigActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("id", serverCondigId);
context.startActivity(intent);
}
}
package chat.rocket.android;
import android.app.Application;
import com.facebook.stetho.Stetho;
import com.uphyca.stetho_realm.RealmInspectorModulesProvider;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import timber.log.Timber;
/**
* Customized Application-class for Rocket.Chat
*/
public class RocketChatApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
@Override public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
Timber.plant(new Timber.DebugTree());
Realm.init(this);
Realm.setDefaultConfiguration(new RealmConfiguration.Builder()
.deleteRealmIfMigrationNeeded()
.build());
Realm.init(this);
Realm.setDefaultConfiguration(
new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build());
Stetho.initialize(
Stetho.newInitializerBuilder(this)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
.enableWebKitInspector(RealmInspectorModulesProvider.builder(this).build())
.build());
Stetho.initialize(Stetho.newInitializerBuilder(this)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
.enableWebKitInspector(RealmInspectorModulesProvider.builder(this).build())
.build());
//TODO: add periodic trigger for RocketChatService.keepalive(this) here!
}
//TODO: add periodic trigger for RocketChatService.keepalive(this) here!
}
}
package chat.rocket.android.activity;
import android.support.v7.app.AppCompatActivity;
import java.util.List;
import java.util.UUID;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.service.RocketChatService;
import io.realm.Realm;
import io.realm.RealmResults;
import java.util.List;
import java.util.UUID;
import jp.co.crowdworks.realm_java_helpers.RealmListObserver;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
abstract class AbstractAuthedActivity extends AppCompatActivity {
private RealmListObserver<ServerConfig> mInsertEmptyRecordIfNoConfigurationExists = new RealmListObserver<ServerConfig>() {
@Override
protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class).findAll();
private RealmListObserver<ServerConfig> serverConfigEmptinessObserver =
new RealmListObserver<ServerConfig>() {
@Override protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class).findAll();
}
@Override
protected void onCollectionChanged(List<ServerConfig> list) {
if (list.isEmpty()) {
final String newId = UUID.randomUUID().toString();
RealmHelperBolts
.executeTransaction(realm -> realm.createObject(ServerConfig.class, newId))
.continueWith(new LogcatIfError());
}
@Override protected void onCollectionChanged(List<ServerConfig> list) {
if (list.isEmpty()) {
final String newId = UUID.randomUUID().toString();
RealmHelperBolts.executeTransaction(
realm -> realm.createObject(ServerConfig.class, newId))
.continueWith(new LogcatIfError());
}
}
};
private RealmListObserver<ServerConfig> mShowConfigActivityIfNeeded = new RealmListObserver<ServerConfig>() {
};
@Override
protected RealmResults<ServerConfig> queryItems(Realm realm) {
return ServerConfig.queryLoginRequiredConnections(realm).findAll();
private RealmListObserver<ServerConfig> loginRequiredServerConfigObserver =
new RealmListObserver<ServerConfig>() {
@Override protected RealmResults<ServerConfig> queryItems(Realm realm) {
return ServerConfig.queryLoginRequiredConnections(realm).findAll();
}
@Override
protected void onCollectionChanged(List<ServerConfig> list) {
ServerConfigActivity.launchFor(AbstractAuthedActivity.this, list);
@Override protected void onCollectionChanged(List<ServerConfig> list) {
ServerConfigActivity.launchFor(AbstractAuthedActivity.this, list);
}
};
@Override
protected void onResume() {
super.onResume();
RocketChatService.keepalive(this);
mInsertEmptyRecordIfNoConfigurationExists.sub();
mShowConfigActivityIfNeeded.sub();
}
@Override
protected void onPause() {
mShowConfigActivityIfNeeded.unsub();
mInsertEmptyRecordIfNoConfigurationExists.unsub();
super.onPause();
}
};
@Override protected void onResume() {
super.onResume();
RocketChatService.keepalive(this);
serverConfigEmptinessObserver.sub();
loginRequiredServerConfigObserver.sub();
}
@Override protected void onPause() {
loginRequiredServerConfigObserver.unsub();
serverConfigEmptinessObserver.unsub();
super.onPause();
}
}
......@@ -3,33 +3,34 @@ package chat.rocket.android.activity;
import android.support.annotation.IdRes;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import chat.rocket.android.helper.OnBackPressListener;
abstract class AbstractFragmentActivity extends AppCompatActivity {
protected abstract @IdRes int getLayoutContainerForFragment();
protected abstract @IdRes int getLayoutContainerForFragment();
@Override
public void onBackPressed(){
Fragment f = getSupportFragmentManager().findFragmentById(getLayoutContainerForFragment());
if(f instanceof OnBackPressListener &&
((OnBackPressListener) f).onBackPressed()){
//consumed. do nothing.
}
else super.onBackPressed();
}
@Override public void onBackPressed() {
Fragment fragment =
getSupportFragmentManager().findFragmentById(getLayoutContainerForFragment());
protected void showFragment(Fragment f) {
getSupportFragmentManager().beginTransaction()
.replace(getLayoutContainerForFragment(), f)
.commit();
if (fragment instanceof OnBackPressListener
&& ((OnBackPressListener) fragment).onBackPressed()) {
//consumed. do nothing.
} else {
super.onBackPressed();
}
}
protected void showFragmentWithBackStack(Fragment f) {
getSupportFragmentManager().beginTransaction()
.replace(getLayoutContainerForFragment(), f)
.addToBackStack(null)
.commit();
}
protected void showFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(getLayoutContainerForFragment(), fragment)
.commit();
}
protected void showFragmentWithBackStack(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(getLayoutContainerForFragment(), fragment)
.addToBackStack(null)
.commit();
}
}
......@@ -2,25 +2,26 @@ package chat.rocket.android.activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import chat.rocket.android.R;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ServerConfig;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
/**
* Entry-point for Rocket.Chat.Android application.
*/
public class MainActivity extends AbstractAuthedActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState==null) {
RealmHelperBolts.executeTransaction(realm -> {
for(ServerConfig config: ServerConfig.queryActiveConnections(realm).findAll()) {
config.setTokenVerified(false);
}
return null;
}).continueWith(new LogcatIfError());
if (savedInstanceState == null) {
RealmHelperBolts.executeTransaction(realm -> {
for (ServerConfig config : ServerConfig.queryActiveConnections(realm).findAll()) {
config.setTokenVerified(false);
}
return null;
}).continueWith(new LogcatIfError());
}
}
}
......@@ -5,181 +5,176 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import java.util.List;
import chat.rocket.android.LaunchUtil;
import chat.rocket.android.R;
import chat.rocket.android.fragment.server_config.ConnectingToHostFragment;
import chat.rocket.android.fragment.server_config.InputHostnameFragment;
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.service.RocketChatService;
import io.realm.Realm;
import io.realm.RealmList;
import io.realm.RealmQuery;
import java.util.List;
import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver;
/**
* Activity for Login, Sign-up, and Connecting...
*/
public class ServerConfigActivity extends AbstractFragmentActivity {
@Override
protected int getLayoutContainerForFragment() {
return R.id.content;
}
private String mServerConfigId;
private RealmObjectObserver<ServerConfig> mServerConfigObserver = new RealmObjectObserver<ServerConfig>() {
@Override
protected RealmQuery<ServerConfig> query(Realm realm) {
return realm.where(ServerConfig.class).equalTo("id", mServerConfigId);
}
@Override
protected void onChange(ServerConfig config) {
onRenderServerConfig(config);
}
};
public static boolean launchFor(Context context, List<ServerConfig> configList) {
for (ServerConfig config: configList) {
if (TextUtils.isEmpty(config.getHostname())) {
return launchFor(context, config);
}
else if (!TextUtils.isEmpty(config.getConnectionError())) {
return launchFor(context, config);
}
private String serverConfigId;
private RealmObjectObserver<ServerConfig> serverConfigObserver =
new RealmObjectObserver<ServerConfig>() {
@Override protected RealmQuery<ServerConfig> query(Realm realm) {
return realm.where(ServerConfig.class).equalTo("id", serverConfigId);
}
for (ServerConfig config: configList) {
if (config.getProviders().isEmpty()) {
return launchFor(context, config);
}
@Override protected void onChange(ServerConfig config) {
onRenderServerConfig(config);
}
};
for (ServerConfig config: configList) {
if (TextUtils.isEmpty(config.getSelectedProviderName())) {
return launchFor(context, config);
}
}
/**
* Start the ServerConfigActivity with considering the priority of ServerConfig in the list.
*/
public static boolean launchFor(Context context, List<ServerConfig> configList) {
for (ServerConfig config : configList) {
if (TextUtils.isEmpty(config.getHostname())) {
return launchFor(context, config);
} else if (!TextUtils.isEmpty(config.getConnectionError())) {
return launchFor(context, config);
}
}
for (ServerConfig config: configList) {
if (TextUtils.isEmpty(config.getToken())) {
return launchFor(context, config);
}
}
for (ServerConfig config : configList) {
if (config.getAuthProviders().isEmpty()) {
return launchFor(context, config);
}
}
for (ServerConfig config: configList) {
if (!config.isTokenVerified()) {
return launchFor(context, config);
}
}
for (ServerConfig config : configList) {
if (TextUtils.isEmpty(config.getSelectedProviderName())) {
return launchFor(context, config);
}
}
return false;
for (ServerConfig config : configList) {
if (TextUtils.isEmpty(config.getToken())) {
return launchFor(context, config);
}
}
private static boolean launchFor(Context context, ServerConfig config) {
LaunchUtil.showServerConfigActivity(context, config.getId());
return true;
for (ServerConfig config : configList) {
if (!config.isTokenVerified()) {
return launchFor(context, config);
}
}
return false;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
private static boolean launchFor(Context context, ServerConfig config) {
LaunchUtil.showServerConfigActivity(context, config.getId());
return true;
}
Intent intent = getIntent();
if (intent==null || intent.getExtras()==null) {
finish();
return;
}
@Override protected int getLayoutContainerForFragment() {
return R.id.content;
}
mServerConfigId = intent.getStringExtra("id");
if (TextUtils.isEmpty(mServerConfigId)) {
finish();
return;
}
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_screen);
Intent intent = getIntent();
if (intent == null || intent.getExtras() == null) {
finish();
return;
}
@Override
protected void onResume() {
super.onResume();
RocketChatService.keepalive(this);
mServerConfigObserver.sub();
serverConfigId = intent.getStringExtra("id");
if (TextUtils.isEmpty(serverConfigId)) {
finish();
return;
}
@Override
protected void onPause() {
mServerConfigObserver.unsub();
super.onPause();
}
setContentView(R.layout.simple_screen);
}
private void onRenderServerConfig(ServerConfig config) {
if (config==null) {
finish();
return;
}
@Override protected void onResume() {
super.onResume();
RocketChatService.keepalive(this);
serverConfigObserver.sub();
}
if (config.isTokenVerified()) {
finish();
return;
}
@Override protected void onPause() {
serverConfigObserver.unsub();
super.onPause();
}
final String token = config.getToken();
if (!TextUtils.isEmpty(token)) {
return;
}
private void onRenderServerConfig(ServerConfig config) {
if (config == null) {
finish();
return;
}
final String selectedProviderName = config.getSelectedProviderName();
if (!TextUtils.isEmpty(selectedProviderName)) {
if (config.isTokenVerified()) {
finish();
return;
}
return;
}
final String token = config.getToken();
if (!TextUtils.isEmpty(token)) {
return;
}
RealmList<ServerAuthProvider> providers = config.getProviders();
if (!providers.isEmpty()) {
final String selectedProviderName = config.getSelectedProviderName();
if (!TextUtils.isEmpty(selectedProviderName)) {
return;
}
return;
}
final String error = config.getConnectionError();
String hostname = config.getHostname();
if (!TextUtils.isEmpty(hostname) && TextUtils.isEmpty(error)) {
showFragment(new ConnectingToHostFragment());
return;
}
RealmList<MeteorLoginServiceConfiguration> providers = config.getAuthProviders();
if (!providers.isEmpty()) {
showFragment(new InputHostnameFragment());
return;
}
@Override
protected void showFragment(Fragment f) {
injectIdArgTo(f);
super.showFragment(f);
final String error = config.getConnectionError();
String hostname = config.getHostname();
if (!TextUtils.isEmpty(hostname) && TextUtils.isEmpty(error)) {
showFragment(new ConnectingToHostFragment());
return;
}
@Override
protected void showFragmentWithBackStack(Fragment f) {
injectIdArgTo(f);
super.showFragmentWithBackStack(f);
}
showFragment(new InputHostnameFragment());
}
private void injectIdArgTo(Fragment f) {
Bundle args = f.getArguments();
if(args==null) args = new Bundle();
args.putString("id", mServerConfigId);
f.setArguments(args);
}
@Override protected void showFragment(Fragment fragment) {
injectServerConfigIdArgTo(fragment);
super.showFragment(fragment);
}
@Override
public void onBackPressed() {
if (ServerConfig.hasActiveConnection()) {
super.onBackPressed();
}
else {
moveTaskToBack(true);
}
@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("id", serverConfigId);
fragment.setArguments(args);
}
@Override public void onBackPressed() {
if (ServerConfig.hasActiveConnection()) {
super.onBackPressed();
} else {
moveTaskToBack(true);
}
}
}
......@@ -8,24 +8,30 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Fragment base class for this Application.
*/
public abstract class AbstractFragment extends Fragment {
protected View mRootView;
protected abstract @LayoutRes int getLayout();
protected abstract void onSetupView();
protected View rootView;
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(getLayout(), container,false);
onSetupView();
return mRootView;
}
protected abstract @LayoutRes int getLayout();
protected abstract void onSetupView();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(getLayout(), container, false);
onSetupView();
return rootView;
}
protected void finish() {
if(getFragmentManager().getBackStackEntryCount()==0){
getActivity().finish();
}
else {
getFragmentManager().popBackStack();
}
protected void finish() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
getActivity().finish();
} else {
getFragmentManager().popBackStack();
}
}
}
......@@ -2,26 +2,25 @@ package chat.rocket.android.fragment.server_config;
import android.os.Bundle;
import android.support.annotation.Nullable;
import chat.rocket.android.fragment.AbstractFragment;
import chat.rocket.android.helper.TextUtils;
abstract class AbstractServerConfigFragment extends AbstractFragment {
protected String mServerConfigId;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
protected String serverConfigId;
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args==null) {
finish();
return;
}
Bundle args = getArguments();
if (args == null) {
finish();
return;
}
mServerConfigId = args.getString("id");
if (TextUtils.isEmpty(mServerConfigId)) {
finish();
return;
}
serverConfigId = args.getString("id");
if (TextUtils.isEmpty(serverConfigId)) {
finish();
return;
}
}
}
......@@ -2,14 +2,15 @@ package chat.rocket.android.fragment.server_config;
import chat.rocket.android.R;
/**
* Just showing "connecting..." screen.
*/
public class ConnectingToHostFragment extends AbstractServerConfigFragment {
@Override
protected int getLayout() {
return R.layout.fragment_wait_for_connection;
}
@Override protected int getLayout() {
return R.layout.fragment_wait_for_connection;
}
@Override
protected void onSetupView() {
@Override protected void onSetupView() {
}
}
}
......@@ -2,12 +2,8 @@ package chat.rocket.android.fragment.server_config;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
import chat.rocket.android.R;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
......@@ -16,85 +12,86 @@ import io.realm.Realm;
import io.realm.RealmQuery;
import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
import org.json.JSONObject;
/**
* Input server host.
*/
public class InputHostnameFragment extends AbstractServerConfigFragment {
public InputHostnameFragment(){}
@Override
protected int getLayout() {
return R.layout.fragment_input_hostname;
private Handler errorShowingHandler = new Handler() {
@Override public void handleMessage(Message msg) {
Toast.makeText(rootView.getContext(), (String) msg.obj, Toast.LENGTH_SHORT).show();
}
RealmObjectObserver<ServerConfig> mObserver = new RealmObjectObserver<ServerConfig>() {
@Override
protected RealmQuery<ServerConfig> query(Realm realm) {
return realm.where(ServerConfig.class).equalTo("id", mServerConfigId);
}
@Override
protected void onChange(ServerConfig config) {
onRenderServerConfig(config);
}
};
@Override
protected void onSetupView() {
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(TextUtils.or(editor.getText(), editor.getHint()), "").toString();
RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", mServerConfigId)
.put("hostname", hostname)
.put("connectionError", JSONObject.NULL)))
.continueWith(new LogcatIfError());
});
mObserver.sub();
};
RealmObjectObserver<ServerConfig> serverConfigObserver = new RealmObjectObserver<ServerConfig>() {
@Override protected RealmQuery<ServerConfig> query(Realm realm) {
return realm.where(ServerConfig.class).equalTo("id", serverConfigId);
}
@Override
public void onResume() {
super.onResume();
mObserver.keepalive();
@Override protected void onChange(ServerConfig config) {
onRenderServerConfig(config);
}
};
@Override
public void onDestroyView() {
mObserver.unsub();
super.onDestroyView();
}
public InputHostnameFragment() {
}
private Handler mShowError = new Handler() {
@Override
public void handleMessage(Message msg) {
Toast.makeText(mRootView.getContext(), (String) msg.obj, Toast.LENGTH_SHORT).show();
}
};
private void showError(String errString) {
mShowError.removeMessages(0);
Message m = Message.obtain(mShowError, 0, errString);
mShowError.sendMessageDelayed(m, 160);
}
@Override protected int getLayout() {
return R.layout.fragment_input_hostname;
}
private void onRenderServerConfig(ServerConfig config) {
final TextView editor = (TextView) mRootView.findViewById(R.id.editor_hostname);
if (!TextUtils.isEmpty(config.getHostname())) editor.setText(config.getHostname());
if (!TextUtils.isEmpty(config.getConnectionError())) {
clearConnectionErrorAndHostname();
showError(config.getConnectionError());
}
}
@Override protected void onSetupView() {
rootView.findViewById(R.id.btn_connect).setOnClickListener(view -> handleConnect());
private void clearConnectionErrorAndHostname() {
RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", mServerConfigId)
.put("hostname", JSONObject.NULL)
.put("connectionError", JSONObject.NULL)))
.continueWith(new LogcatIfError());
serverConfigObserver.sub();
}
private void handleConnect() {
final TextView editor = (TextView) rootView.findViewById(R.id.editor_hostname);
final String hostname =
TextUtils.or(TextUtils.or(editor.getText(), editor.getHint()), "").toString();
RealmHelperBolts.executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class,
new JSONObject().put("id", serverConfigId)
.put("hostname", hostname)
.put("connectionError", JSONObject.NULL))).continueWith(new LogcatIfError());
}
@Override public void onResume() {
super.onResume();
serverConfigObserver.keepalive();
}
@Override public void onDestroyView() {
serverConfigObserver.unsub();
super.onDestroyView();
}
private void showError(String errString) {
errorShowingHandler.removeMessages(0);
Message msg = Message.obtain(errorShowingHandler, 0, errString);
errorShowingHandler.sendMessageDelayed(msg, 160);
}
private void onRenderServerConfig(ServerConfig config) {
final TextView editor = (TextView) rootView.findViewById(R.id.editor_hostname);
if (!TextUtils.isEmpty(config.getHostname())) {
editor.setText(config.getHostname());
}
if (!TextUtils.isEmpty(config.getConnectionError())) {
clearConnectionErrorAndHostname();
showError(config.getConnectionError());
}
}
private void clearConnectionErrorAndHostname() {
RealmHelperBolts.executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class,
new JSONObject().put("id", serverConfigId)
.put("hostname", JSONObject.NULL)
.put("connectionError", JSONObject.NULL))).continueWith(new LogcatIfError());
}
}
......@@ -4,12 +4,14 @@ import bolts.Continuation;
import bolts.Task;
import timber.log.Timber;
/**
* Bolts-Task continuation for just logging if error occurred.
*/
public class LogcatIfError implements Continuation {
@Override
public Object then(Task task) throws Exception {
if (task.isFaulted()) {
Timber.w(task.getError());
}
return task;
@Override public Object then(Task task) throws Exception {
if (task.isFaulted()) {
Timber.w(task.getError());
}
return task;
}
}
package chat.rocket.android.helper;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
/**
* Helper class for OkHttp client.
*/
public class OkHttpHelper {
private static OkHttpClient sHttpClientForWS;
public static OkHttpClient getClientForWebSocket() {
private static OkHttpClient sHttpClientForWS;
if (sHttpClientForWS==null) {
sHttpClientForWS = new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.NANOSECONDS)
.addNetworkInterceptor(new StethoInterceptor())
.build();
}
return sHttpClientForWS;
/**
* acquire OkHttpClient instance for WebSocket connection.
*/
public static OkHttpClient getClientForWebSocket() {
if (sHttpClientForWS == null) {
sHttpClientForWS = new OkHttpClient.Builder().readTimeout(0, TimeUnit.NANOSECONDS)
.addNetworkInterceptor(new StethoInterceptor())
.build();
}
return sHttpClientForWS;
}
}
package chat.rocket.android.helper;
/**
* Interface that just have onBackPressed().
*/
public interface OnBackPressListener {
boolean onBackPressed();
/**
* onBackPressed
*
* @return whether back is handled or not.
*/
boolean onBackPressed();
}
package chat.rocket.android.helper;
/**
* Text Utility class like android.text.TextUtils.
*/
public class TextUtils {
public static boolean isEmpty(CharSequence str) {
// same definition as android.text.TextUtils#isEmpty().
return str == null || str.length() == 0;
}
public static CharSequence or(CharSequence str, CharSequence defaultValue) {
if (isEmpty(str)) return defaultValue;
return str;
/**
* 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) {
// same definition as android.text.TextUtils#isEmpty().
return str == null || str.length() == 0;
}
/**
* Returns str if it is not empty; otherwise defaultValue is returned.
*/
@SuppressWarnings("PMD.ShortMethodName")
public static CharSequence or(CharSequence str,
CharSequence defaultValue) {
if (isEmpty(str)) {
return defaultValue;
}
return str;
}
}
package chat.rocket.android.model;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* subscription model for "meteor_accounts_loginServiceConfiguration".
*/
@SuppressWarnings("PMD.ShortVariable")
public class MeteorLoginServiceConfiguration
extends RealmObject {
@PrimaryKey private String id;
private String service;
private String consumerKey; //for Twitter
private String appId; //for Facebook
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, ...
}
package chat.rocket.android.model;
import org.json.JSONObject;
import chat.rocket.android.helper.LogcatIfError;
import hugo.weaving.DebugLog;
import io.realm.Realm;
......@@ -11,96 +9,96 @@ import io.realm.RealmQuery;
import io.realm.annotations.PrimaryKey;
import jp.co.crowdworks.realm_java_helpers.RealmHelper;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
import org.json.JSONObject;
/**
* Server configuration.
*/
@SuppressWarnings("PMD.ShortVariable")
public class ServerConfig extends RealmObject {
@PrimaryKey
private String id;
private String hostname;
private String connectionError;
private String token;
private boolean tokenVerified;
private RealmList<ServerAuthProvider> providers;
private String selectedProviderName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getConnectionError() {
return connectionError;
}
public void setConnectionError(String connectionError) {
this.connectionError = connectionError;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public boolean isTokenVerified() {
return tokenVerified;
}
public void setTokenVerified(boolean tokenVerified) {
this.tokenVerified = tokenVerified;
}
public RealmList<ServerAuthProvider> getProviders() {
return providers;
}
public void setProviders(RealmList<ServerAuthProvider> providers) {
this.providers = providers;
}
public String getSelectedProviderName() {
return selectedProviderName;
}
public void setSelectedProviderName(String selectedProviderName) {
this.selectedProviderName = selectedProviderName;
}
public static RealmQuery<ServerConfig> queryLoginRequiredConnections(Realm realm) {
return realm.where(ServerConfig.class)
.equalTo("tokenVerified", false);
}
public static RealmQuery<ServerConfig> queryActiveConnections(Realm realm) {
return realm.where(ServerConfig.class)
.isNotNull("token");
}
public static boolean hasActiveConnection() {
ServerConfig config = RealmHelper.executeTransactionForRead(realm ->
queryActiveConnections(realm).findFirst());
return config != null;
}
@DebugLog
public static void logError(String id, Exception e) {
RealmHelperBolts
.executeTransaction(realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class, new JSONObject()
.put("id", id)
.put("connectionError", e.getMessage())))
.continueWith(new LogcatIfError());
}
@PrimaryKey private String id;
private String hostname;
private String connectionError;
private String token;
private boolean tokenVerified;
private RealmList<MeteorLoginServiceConfiguration> authProviders;
private String selectedProviderName;
public static RealmQuery<ServerConfig> queryLoginRequiredConnections(Realm realm) {
return realm.where(ServerConfig.class).equalTo("tokenVerified", false);
}
public static RealmQuery<ServerConfig> queryActiveConnections(Realm realm) {
return realm.where(ServerConfig.class).isNotNull("token");
}
public static boolean hasActiveConnection() {
ServerConfig config =
RealmHelper.executeTransactionForRead(realm -> queryActiveConnections(realm).findFirst());
return config != null;
}
@DebugLog public static void logError(String id, Exception exception) {
RealmHelperBolts.executeTransaction(
realm -> realm.createOrUpdateObjectFromJson(ServerConfig.class,
new JSONObject().put("id", id).put("connectionError", exception.getMessage())))
.continueWith(new LogcatIfError());
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getConnectionError() {
return connectionError;
}
public void setConnectionError(String connectionError) {
this.connectionError = connectionError;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public boolean isTokenVerified() {
return tokenVerified;
}
public void setTokenVerified(boolean tokenVerified) {
this.tokenVerified = tokenVerified;
}
public RealmList<MeteorLoginServiceConfiguration> getAuthProviders() {
return authProviders;
}
public void setAuthProviders(RealmList<MeteorLoginServiceConfiguration> authProviders) {
this.authProviders = authProviders;
}
public String getSelectedProviderName() {
return selectedProviderName;
}
public void setSelectedProviderName(String selectedProviderName) {
this.selectedProviderName = selectedProviderName;
}
}
package chat.rocket.android.model.doc;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class MeteorLoginServiceConfiguration extends RealmObject {
@PrimaryKey
private String id;
private String service;
private String consumerKey; //for Twitter
private String appId;//for Facebook
private String clientId;//for other auth providers
}
package chat.rocket.android.service;
/**
* interface for observer and ddp_subscription.
*/
public interface Registerable {
void register();
void keepalive();
void unregister();
/**
* register.
*/
void register();
/**
* keepalive.
*/
void keepalive();
/**
* unregister.
*/
void unregister();
}
......@@ -5,99 +5,105 @@ import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import bolts.Task;
import chat.rocket.android.model.ServerConfig;
import io.realm.Realm;
import io.realm.RealmResults;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import jp.co.crowdworks.realm_java_helpers.RealmListObserver;
/**
* Background service for Rocket.Chat.Application class.
*/
public class RocketChatService extends Service {
public static void keepalive(Context context) {
context.startService(new Intent(context, RocketChatService.class));
}
public static void kill(Context context) {
context.stopService(new Intent(context, RocketChatService.class));
}
private HashMap<String, RocketChatWebSocketThread> mWebSocketThreads;
private RealmListObserver<ServerConfig> mConnectionRequiredServerConfigObserver = new RealmListObserver<ServerConfig>() {
@Override
protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class)
.isNotNull("hostname")
.isNull("connectionError")
.findAll();
private HashMap<String, RocketChatWebSocketThread> webSocketThreads;
private RealmListObserver<ServerConfig> connectionRequiredServerConfigObserver =
new RealmListObserver<ServerConfig>() {
@Override protected RealmResults<ServerConfig> queryItems(Realm realm) {
return realm.where(ServerConfig.class)
.isNotNull("hostname")
.isNull("connectionError")
.findAll();
}
@Override
protected void onCollectionChanged(List<ServerConfig> list) {
syncWebSocketThreadsWith(list);
@Override protected void onCollectionChanged(List<ServerConfig> list) {
syncWebSocketThreadsWith(list);
}
};
};
@Override
public void onCreate() {
super.onCreate();
mWebSocketThreads = new HashMap<>();
}
/**
* ensure RocketChatService alive.
*/
public static void keepalive(Context context) {
context.startService(new Intent(context, RocketChatService.class));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mConnectionRequiredServerConfigObserver.keepalive();
return START_STICKY;
}
/**
* force stop RocketChatService.
*/
public static void kill(Context context) {
context.stopService(new Intent(context, RocketChatService.class));
}
private void syncWebSocketThreadsWith(List<ServerConfig> configList) {
final Iterator<Map.Entry<String, RocketChatWebSocketThread>> it = mWebSocketThreads.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<String, RocketChatWebSocketThread> e = it.next();
String id = e.getKey();
boolean found = false;
for(ServerConfig config: configList) {
if (id.equals(config.getId())) {
found = true;
break;
}
}
if (!found) {
RocketChatWebSocketThread.terminate(e.getValue());
it.remove();
}
}
@Override public void onCreate() {
super.onCreate();
webSocketThreads = new HashMap<>();
}
for(ServerConfig config: configList) {
findOrCreateWebSocketThread(config).onSuccess(task -> {
RocketChatWebSocketThread thread = task.getResult();
thread.syncStateWith(config);
return null;
});
}
}
@Override public int onStartCommand(Intent intent, int flags, int startId) {
connectionRequiredServerConfigObserver.keepalive();
return START_STICKY;
}
private Task<RocketChatWebSocketThread> findOrCreateWebSocketThread(final ServerConfig config) {
final String id = config.getId();
if (mWebSocketThreads.containsKey(id)) {
return Task.forResult(mWebSocketThreads.get(id));
}
else {
return RocketChatWebSocketThread.getStarted(getApplicationContext(), config).onSuccessTask(task -> {
mWebSocketThreads.put(id, task.getResult());
return task;
});
private void syncWebSocketThreadsWith(List<ServerConfig> configList) {
final Iterator<Map.Entry<String, RocketChatWebSocketThread>> iterator =
webSocketThreads.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, RocketChatWebSocketThread> entry = iterator.next();
String serverConfigId = entry.getKey();
boolean found = false;
for (ServerConfig config : configList) {
if (serverConfigId.equals(config.getId())) {
found = true;
break;
}
}
if (!found) {
RocketChatWebSocketThread.terminate(entry.getValue());
iterator.remove();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
for (ServerConfig config : configList) {
findOrCreateWebSocketThread(config).onSuccess(task -> {
RocketChatWebSocketThread thread = task.getResult();
thread.syncStateWith(config);
return null;
});
}
}
\ No newline at end of file
}
private Task<RocketChatWebSocketThread> findOrCreateWebSocketThread(final ServerConfig config) {
final String serverConfigId = config.getId();
if (webSocketThreads.containsKey(serverConfigId)) {
return Task.forResult(webSocketThreads.get(serverConfigId));
} else {
return RocketChatWebSocketThread.getStarted(getApplicationContext(), config)
.onSuccessTask(task -> {
webSocketThreads.put(serverConfigId, task.getResult());
return task;
});
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
package chat.rocket.android.service.ddp_subscriber;
import android.content.Context;
import android.text.TextUtils;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.service.Registerable;
import chat.rocket.android.ws.RocketChatWebSocketAPI;
import chat.rocket.android_ddp.DDPSubscription;
import io.realm.Realm;
import io.realm.RealmObject;
import java.util.Iterator;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
import org.json.JSONException;
import org.json.JSONObject;
import rx.Subscription;
import timber.log.Timber;
abstract class AbstractDDPDocEventSubscriber implements Registerable {
protected final Context context;
protected final RocketChatWebSocketAPI webSocketAPI;
private String subscriptionId;
private Subscription rxSubscription;
protected AbstractDDPDocEventSubscriber(Context context, RocketChatWebSocketAPI api) {
this.context = context;
this.webSocketAPI = api;
}
protected abstract String getSubscriptionName();
protected abstract String getSubscriptionCallbackName();
protected abstract Class<? extends RealmObject> getModelClass();
protected JSONObject customizeFieldJson(JSONObject json) {
return json;
}
@Override public void register() {
webSocketAPI.subscribe(getSubscriptionName(), null).onSuccess(task -> {
subscriptionId = task.getResult().id;
return null;
}).continueWith(task -> {
if (task.isFaulted()) {
Timber.w(task.getError(), "DDP subscription failed.");
}
return null;
});
RealmHelperBolts.executeTransaction(realm -> {
realm.delete(getModelClass());
return null;
}).onSuccess(task -> {
registerSubscriptionCallback();
return null;
}).continueWith(new LogcatIfError());
}
private void registerSubscriptionCallback() {
rxSubscription = webSocketAPI.getSubscriptionCallback()
.filter(event -> event instanceof DDPSubscription.DocEvent)
.cast(DDPSubscription.DocEvent.class)
.filter(event -> getSubscriptionCallbackName().equals(event.collection))
.subscribe(docEvent -> {
try {
if (docEvent instanceof DDPSubscription.Added.Before) {
onDocumentAdded((DDPSubscription.Added) docEvent); //ignore Before
} else if (docEvent instanceof DDPSubscription.Added) {
onDocumentAdded((DDPSubscription.Added) docEvent);
} else if (docEvent instanceof DDPSubscription.Removed) {
onDocumentRemoved((DDPSubscription.Removed) docEvent);
} else if (docEvent instanceof DDPSubscription.Changed) {
onDocumentChanged((DDPSubscription.Changed) docEvent);
} else if (docEvent instanceof DDPSubscription.MovedBefore) {
//ignore movedBefore
}
} catch (Exception exception) {
Timber.w(exception, "failed to handle subscription callback");
}
});
}
protected void onDocumentAdded(DDPSubscription.Added docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentAdded(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
private void onDocumentAdded(Realm realm, DDPSubscription.Added docEvent) throws JSONException {
//executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID);
mergeJson(json, docEvent.fields);
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJson(json));
}
protected void onDocumentChanged(DDPSubscription.Changed docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentChanged(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
private void onDocumentChanged(Realm realm, DDPSubscription.Changed docEvent)
throws JSONException {
//executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID);
for (int i = 0; i < docEvent.cleared.length(); i++) {
String fieldToDelete = docEvent.cleared.getString(i);
json.remove(fieldToDelete);
}
mergeJson(json, docEvent.fields);
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJson(json));
}
protected void onDocumentRemoved(DDPSubscription.Removed docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentRemoved(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
private void onDocumentRemoved(Realm realm, DDPSubscription.Removed docEvent)
throws JSONException {
//executed in RealmTransaction
realm.where(getModelClass()).equalTo("id", docEvent.docID).findAll().deleteAllFromRealm();
}
private void mergeJson(JSONObject target, JSONObject src) throws JSONException {
Iterator<String> iterator = src.keys();
while (iterator.hasNext()) {
String key = iterator.next();
target.put(key, src.get(key));
}
}
@Override public void keepalive() {
}
@Override public void unregister() {
if (rxSubscription != null) {
rxSubscription.unsubscribe();
}
if (!TextUtils.isEmpty(subscriptionId)) {
webSocketAPI.unsubscribe(subscriptionId).continueWith(new LogcatIfError());
}
}
}
package chat.rocket.android.service.ddp_subscriber;
import android.content.Context;
import chat.rocket.android.model.MeteorLoginServiceConfiguration;
import chat.rocket.android.ws.RocketChatWebSocketAPI;
import io.realm.RealmObject;
/**
* meteor.loginServiceConfiguration subscriber
*/
public class LoginServiceConfigurationSubscriber extends AbstractDDPDocEventSubscriber {
public LoginServiceConfigurationSubscriber(Context context, RocketChatWebSocketAPI api) {
super(context, api);
}
@Override protected String getSubscriptionName() {
return "meteor.loginServiceConfiguration";
}
@Override protected String getSubscriptionCallbackName() {
return "meteor_accounts_loginServiceConfiguration";
}
@Override protected Class<? extends RealmObject> getModelClass() {
return MeteorLoginServiceConfiguration.class;
}
}
package chat.rocket.android.service.ddp_subscription;
import android.content.Context;
import android.text.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.service.Registerable;
import chat.rocket.android.ws.RocketChatWebSocketAPI;
import chat.rocket.android_ddp.DDPSubscription;
import io.realm.Realm;
import io.realm.RealmObject;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
import rx.Subscription;
import timber.log.Timber;
abstract class AbstractDDPDocEventSubscriber implements Registerable {
protected final Context mContext;
protected final RocketChatWebSocketAPI mAPI;
private String mID;
private Subscription mSubscription;
public AbstractDDPDocEventSubscriber(Context context, RocketChatWebSocketAPI api) {
mContext = context;
mAPI = api;
}
protected abstract String getSubscriptionName();
protected abstract String getSubscriptionCallbackName();
protected abstract Class<? extends RealmObject> getModelClass();
protected JSONObject customizeFieldJSON(JSONObject json) { return json; }
@Override
public void register() {
mAPI.subscribe(getSubscriptionName(), null).onSuccess(task -> {
mID = task.getResult().id;
return null;
}).continueWith(task -> {
if (task.isFaulted()) {
Timber.w(task.getError());
}
return null;
});
RealmHelperBolts.executeTransaction(realm -> {
realm.delete(getModelClass());
return null;
}).onSuccess(task -> {
registerSubscriptionCallback();
return null;
}).continueWith(new LogcatIfError());
}
private void registerSubscriptionCallback() {
mSubscription = mAPI.getSubscriptionCallback()
.filter(event -> event instanceof DDPSubscription.DocEvent
&& getSubscriptionCallbackName().equals(((DDPSubscription.DocEvent) event).collection))
.cast(DDPSubscription.DocEvent.class)
.subscribe(docEvent -> {
try {
if (docEvent instanceof DDPSubscription.Added.Before) {
onDocumentAdded((DDPSubscription.Added) docEvent); //ignore Before
} else if (docEvent instanceof DDPSubscription.Added) {
onDocumentAdded((DDPSubscription.Added) docEvent);
} else if (docEvent instanceof DDPSubscription.Removed) {
onDocumentRemoved((DDPSubscription.Removed) docEvent);
} else if (docEvent instanceof DDPSubscription.Changed) {
onDocumentChanged((DDPSubscription.Changed) docEvent);
} else if (docEvent instanceof DDPSubscription.MovedBefore) {
//ignore movedBefore
}
} catch (Exception e) {
Timber.w(e);
}
});
}
protected void onDocumentAdded(DDPSubscription.Added docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentAdded(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
protected void onDocumentChanged(DDPSubscription.Changed docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentChanged(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
protected void onDocumentRemoved(DDPSubscription.Removed docEvent) {
RealmHelperBolts.executeTransaction(realm -> {
onDocumentRemoved(realm, docEvent);
return null;
}).continueWith(new LogcatIfError());
}
private void mergeJSON(JSONObject target, JSONObject src) throws JSONException {
Iterator<String> it = src.keys();
while(it.hasNext()) {
String key = it.next();
target.put(key, src.get(key));
}
}
private void onDocumentAdded(Realm realm, DDPSubscription.Added docEvent) throws JSONException {
//executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID);
mergeJSON(json, docEvent.fields);
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json));
}
private void onDocumentChanged(Realm realm, DDPSubscription.Changed docEvent) throws JSONException {
//executed in RealmTransaction
JSONObject json = new JSONObject().put("id", docEvent.docID);
for (int i=0; i<docEvent.cleared.length(); i++) {
String fieldToDelete = docEvent.cleared.getString(i);
json.remove(fieldToDelete);
}
mergeJSON(json, docEvent.fields);
realm.createOrUpdateObjectFromJson(getModelClass(), customizeFieldJSON(json));
}
private void onDocumentRemoved(Realm realm, DDPSubscription.Removed docEvent) throws JSONException {
//executed in RealmTransaction
realm.where(getModelClass()).equalTo("id", docEvent.docID).findAll().deleteAllFromRealm();
}
@Override
public void keepalive() {
}
@Override
public void unregister() {
if (mSubscription != null) mSubscription.unsubscribe();
if (!TextUtils.isEmpty(mID)) {
mAPI.unsubscribe(mID).continueWith(new LogcatIfError());
}
}
}
package chat.rocket.android.service.ddp_subscription;
import android.content.Context;
import chat.rocket.android.model.doc.MeteorLoginServiceConfiguration;
import chat.rocket.android.ws.RocketChatWebSocketAPI;
import io.realm.RealmObject;
public class LoginServiceConfigurationSubscriber extends AbstractDDPDocEventSubscriber {
public LoginServiceConfigurationSubscriber(Context context, RocketChatWebSocketAPI api) {
super(context, api);
}
@Override
protected String getSubscriptionName() {
return "meteor.loginServiceConfiguration";
}
@Override
protected String getSubscriptionCallbackName() {
return "meteor_accounts_loginServiceConfiguration";
}
@Override
protected Class<? extends RealmObject> getModelClass() {
return MeteorLoginServiceConfiguration.class;
}
}
package chat.rocket.android.service.observer;
import android.content.Context;
import chat.rocket.android.service.Registerable;
import chat.rocket.android.ws.RocketChatWebSocketAPI;
import io.realm.RealmObject;
import jp.co.crowdworks.realm_java_helpers.RealmListObserver;
abstract class AbstractModelObserver<T extends RealmObject> extends RealmListObserver<T> implements Registerable {
protected final Context mContext;
protected final RocketChatWebSocketAPI mAPI;
abstract class AbstractModelObserver<T extends RealmObject> extends RealmListObserver<T>
implements Registerable {
public AbstractModelObserver(Context context, RocketChatWebSocketAPI api) {
mContext = context;
mAPI = api;
}
protected final Context context;
protected final RocketChatWebSocketAPI webSocketAPI;
protected AbstractModelObserver(Context context, RocketChatWebSocketAPI api) {
this.context = context;
webSocketAPI = api;
}
@Override
public void register() {
sub();
}
@Override public void register() {
sub();
}
@Override
public void unregister() {
unsub();
}
@Override public void unregister() {
unsub();
}
}
......@@ -7,28 +7,30 @@ import android.util.AttributeSet;
abstract class AbstractCustomFontTextView extends AppCompatTextView {
protected abstract String getFont();
public AbstractCustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public AbstractCustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public AbstractCustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AbstractCustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AbstractCustomFontTextView(Context context) {
super(context);
init();
}
public AbstractCustomFontTextView(Context context) {
super(context);
init();
}
protected abstract String getFont();
private void init() {
String font = getFont();
if (font!=null) {
Typeface tf = TypefaceHelper.getTypeface(getContext(), font);
if (tf!=null) setTypeface(tf);
}
private void init() {
String font = getFont();
if (font != null) {
Typeface typeface = TypefaceHelper.getTypeface(getContext(), font);
if (typeface != null) {
setTypeface(typeface);
}
}
}
}
......@@ -3,21 +3,23 @@ package chat.rocket.android.view;
import android.content.Context;
import android.util.AttributeSet;
/**
* TextView with font-awesome.
*/
public class FontAwesomeTextView extends AbstractCustomFontTextView {
public FontAwesomeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FontAwesomeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FontAwesomeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FontAwesomeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FontAwesomeTextView(Context context) {
super(context);
}
public FontAwesomeTextView(Context context) {
super(context);
}
@Override
protected String getFont() {
return "fontawesome-webfont.ttf";
}
@Override protected String getFont() {
return "fontawesome-webfont.ttf";
}
}
......@@ -3,21 +3,23 @@ package chat.rocket.android.view;
import android.content.Context;
import android.util.AttributeSet;
/**
* TextView with fontello.
*/
public class FontelloTextView extends AbstractCustomFontTextView {
public FontelloTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FontelloTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FontelloTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FontelloTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FontelloTextView(Context context) {
super(context);
}
public FontelloTextView(Context context) {
super(context);
}
@Override
protected String getFont() {
return "fontello.ttf";
}
@Override protected String getFont() {
return "fontello.ttf";
}
}
......@@ -3,29 +3,32 @@ package chat.rocket.android.view;
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
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 {
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>();
public static Typeface getTypeface(Context c, String assetPath) {
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
Typeface t = Typeface.createFromAsset(c.getAssets(),
assetPath);
cache.put(assetPath, t);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface '" + assetPath
+ "' because " + e.getMessage());
return null;
}
}
return cache.get(assetPath);
/**
* read font in assets directory.
*/
public static Typeface getTypeface(Context context, String assetPath) {
synchronized (CACHE) {
if (!CACHE.containsKey(assetPath)) {
try {
Typeface typeface = Typeface.createFromAsset(context.getAssets(), assetPath);
CACHE.put(assetPath, typeface);
} catch (Exception exception) {
Log.e(TAG,
"Could not get typeface '" + assetPath + "' because " + exception.getMessage());
return null;
}
}
return CACHE.get(assetPath);
}
}
}
......@@ -11,106 +11,108 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import chat.rocket.android.R;
import java.util.ArrayList;
/**
* View for indicating "waiting for connection ..." and so on.
*/
public class WaitingView extends LinearLayout {
private ArrayList<View> mDots;
public WaitingView(Context context) {
super(context);
initialize(context, null);
private ArrayList<View> dots;
public WaitingView(Context context) {
super(context);
initialize(context, null);
}
public WaitingView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public WaitingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WaitingView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
int size = context.getResources().getDimensionPixelSize(R.dimen.def_waiting_view_dot_size);
int count = 3;
if (attrs != null) {
TypedArray array =
context.getTheme().obtainStyledAttributes(attrs, R.styleable.WaitingView, 0, 0);
size = array.getDimensionPixelSize(R.styleable.WaitingView_dotSize, size);
count = array.getInteger(R.styleable.WaitingView_dotCount, count);
array.recycle();
}
public WaitingView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
dots = new ArrayList<>();
setOrientation(HORIZONTAL);
for (int i = 0; i < count; i++) {
addDot(context, size);
}
public WaitingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override public void onViewAttachedToWindow(View view) {
start();
}
@Override public void onViewDetachedFromWindow(View view) {
cancel();
}
});
}
private void addDot(Context context, int size) {
FrameLayout frameLayout = new FrameLayout(context);
frameLayout.setLayoutParams(new LinearLayoutCompat.LayoutParams(size * 3 / 2, size * 3 / 2));
ImageView dot = new ImageView(context);
dot.setImageResource(R.drawable.white_circle);
dot.setLayoutParams(new FrameLayout.LayoutParams(size, size, Gravity.CENTER));
frameLayout.addView(dot);
addView(frameLayout);
dots.add(dot);
}
private void start() {
for (int i = 0; i < dots.size(); i++) {
animateDot(dots.get(i), 160 * i, 480, 480);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WaitingView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
int size = context.getResources().getDimensionPixelSize(R.dimen.def_waiting_view_dot_size);
int count = 3;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.WaitingView, 0, 0);
size = a.getDimensionPixelSize(R.styleable.WaitingView_dotSize, size);
count = a.getInteger(R.styleable.WaitingView_dotCount, count);
a.recycle();
}
mDots = new ArrayList<>();
setOrientation(HORIZONTAL);
for (int i=0; i<count; i++) addDot(context, size);
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
start();
}
@Override
public void onViewDetachedFromWindow(View view) {
cancel();
}
});
}
private void addDot(Context context, int size) {
FrameLayout f = new FrameLayout(context);
f.setLayoutParams(new LinearLayoutCompat.LayoutParams(size*3/2, size*3/2));
ImageView dot = new ImageView(context);
dot.setImageResource(R.drawable.white_circle);
dot.setLayoutParams(new FrameLayout.LayoutParams(size, size, Gravity.CENTER));
f.addView(dot);
addView(f);
mDots.add(dot);
}
private void start() {
for(int i=0; i<mDots.size(); i++) {
animateDot(mDots.get(i), 160*i, 480, 480);
}
}
private void animateDot(final View dot, final long startDelay, final long duration, final long interval) {
dot.setScaleX(0);
dot.setScaleY(0);
dot.animate()
.scaleX(1).scaleY(1)
.setDuration(duration)
.setStartDelay(startDelay)
.withEndAction(() -> {
dot.animate()
.scaleX(0).scaleY(0)
.setDuration(duration)
.setStartDelay(0)
.withEndAction(() -> {
animateDot(dot, interval, duration, interval);
})
.start();
})
.start();
}
private void cancel() {
for(View dot: mDots) {
dot.clearAnimation();
}
}
private void animateDot(final View dot, final long startDelay, final long duration,
final long interval) {
dot.setScaleX(0);
dot.setScaleY(0);
dot.animate()
.scaleX(1)
.scaleY(1)
.setDuration(duration)
.setStartDelay(startDelay)
.withEndAction(() -> {
dot.animate()
.scaleX(0)
.scaleY(0)
.setDuration(duration)
.setStartDelay(0)
.withEndAction(() -> {
animateDot(dot, interval, duration, interval);
})
.start();
})
.start();
}
private void cancel() {
for (View dot : dots) {
dot.clearAnimation();
}
}
}
package chat.rocket.android.ws;
import org.json.JSONArray;
import java.util.UUID;
import bolts.Task;
import chat.rocket.android.helper.OkHttpHelper;
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 rx.Observable;
/**
* API for several POST actions.
*/
public class RocketChatWebSocketAPI {
private final DDPClient mDDPClient;
private final String mHostName;
private RocketChatWebSocketAPI(String hostname) {
mDDPClient = new DDPClient(OkHttpHelper.getClientForWebSocket());
mHostName = hostname;
}
public static RocketChatWebSocketAPI create(String hostname) {
return new RocketChatWebSocketAPI(hostname);
}
private final DDPClient ddpClient;
private final String hostname;
public Task<DDPClientCallback.Connect> connect() {
return mDDPClient.connect("wss://" + mHostName + "/websocket");
}
private RocketChatWebSocketAPI(String hostname) {
ddpClient = new DDPClient(OkHttpHelper.getClientForWebSocket());
this.hostname = hostname;
}
public boolean isConnected() {
return mDDPClient.isConnected();
}
/**
* create new API client instance.
*/
public static RocketChatWebSocketAPI create(String hostname) {
return new RocketChatWebSocketAPI(hostname);
}
public void close() {
mDDPClient.close();
}
/**
* Connect to WebSocket server with DDP client.
*/
public Task<DDPClientCallback.Connect> connect() {
return ddpClient.connect("wss://" + hostname + "/websocket");
}
/**
* Returns whether DDP client is connected to WebSocket server.
*/
public boolean isConnected() {
return ddpClient.isConnected();
}
public Task<DDPSubscription.Ready> subscribe(final String name, JSONArray param) {
return mDDPClient.sub(UUID.randomUUID().toString(), name, param);
}
/**
* close connection.
*/
public void close() {
ddpClient.close();
}
public Task<DDPSubscription.NoSub> unsubscribe(final String id) {
return mDDPClient.unsub(id);
}
/**
* Subscribe with DDP client.
*/
public Task<DDPSubscription.Ready> subscribe(final String name, JSONArray param) {
return ddpClient.sub(UUID.randomUUID().toString(), name, param);
}
public Observable<DDPSubscription.Event> getSubscriptionCallback() {
return mDDPClient.getSubscriptionCallback();
}
/**
* Unsubscribe with DDP client.
*/
public Task<DDPSubscription.NoSub> unsubscribe(final String subscriptionId) {
return ddpClient.unsub(subscriptionId);
}
/**
* Returns Observable for handling DDP subscription.
*/
public Observable<DDPSubscription.Event> getSubscriptionCallback() {
return ddpClient.getSubscriptionCallback();
}
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24dp">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--item android:state_enabled="false" android:color="@color/textColorLink" /-->
<item android:color="@color/textColorLink" />
<!--item android:state_enabled="false" android:color="@color/textColorLink" /-->
<item android:color="@color/textColorLink"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/userstatus_away"/>
<stroke android:width="1dp" android:color="@color/userstatus_away_outline" />
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/userstatus_away"/>
<stroke
android:color="@color/userstatus_away_outline"
android:width="1dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/userstatus_busy"/>
<stroke android:width="1dp" android:color="@color/userstatus_busy_outline" />
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/userstatus_busy"/>
<stroke
android:color="@color/userstatus_busy_outline"
android:width="1dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/userstatus_offline"/>
<stroke android:width="1dp" android:color="@color/userstatus_offline_outline" />
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/userstatus_offline"/>
<stroke
android:color="@color/userstatus_offline_outline"
android:width="1dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/userstatus_online"/>
<stroke android:width="1dp" android:color="@color/userstatus_online_outline" />
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/userstatus_online"/>
<stroke
android:color="@color/userstatus_online_outline"
android:width="1dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
<solid android:color="@android:color/white"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
>
<include layout="@layout/sidebar" />
<include layout="@layout/sidebar"/>
<android.support.design.widget.CoordinatorLayout
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/app_name"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/app_name"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/activity_main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</FrameLayout>
<FrameLayout
android:id="@+id/activity_main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
></FrameLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.v4.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
>
<include layout="@layout/sidebar" />
<include layout="@layout/sidebar"/>
<android.support.design.widget.CoordinatorLayout
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/app_name"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/app_name"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/activity_main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</FrameLayout>
<FrameLayout
android:id="@+id/activity_main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
></FrameLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.v4.widget.SlidingPaneLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/avatar_image_size_large" android:layout_height="@dimen/avatar_image_size_large">
android:layout_width="@dimen/avatar_image_size_large"
android:layout_height="@dimen/avatar_image_size_large"
>
<FrameLayout
android:id="@+id/avatar_color"
android:layout_width="@dimen/avatar_image_size_large"
android:layout_height="@dimen/avatar_image_size_large"
android:layout_gravity="center">
<TextView
android:id="@+id/avatar_initials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/avatar_text_size_large"
android:layout_gravity="center"/>
</FrameLayout>
<FrameLayout
android:id="@+id/avatar_color"
android:layout_width="@dimen/avatar_image_size_large"
android:layout_height="@dimen/avatar_image_size_large"
android:layout_gravity="center"
>
<ImageView
android:id="@+id/avatar_img"
android:layout_width="@dimen/avatar_image_size_large"
android:layout_height="@dimen/avatar_image_size_large"
android:src="@drawable/ic_default_avatar"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/avatar_initials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="@dimen/avatar_text_size_large"
/>
</FrameLayout>
<ImageView
android:id="@+id/avatar_img"
android:layout_width="@dimen/avatar_image_size_large"
android:layout_height="@dimen/avatar_image_size_large"
android:scaleType="centerInside"
android:src="@drawable/ic_default_avatar"
/>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/avatar_image_size_normal" android:layout_height="@dimen/avatar_image_size_normal">
android:layout_width="@dimen/avatar_image_size_normal"
android:layout_height="@dimen/avatar_image_size_normal"
>
<FrameLayout
android:id="@+id/avatar_color"
android:layout_width="@dimen/avatar_image_size_normal"
android:layout_height="@dimen/avatar_image_size_normal"
android:layout_gravity="center">
<TextView
android:id="@+id/avatar_initials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/avatar_text_size_normal"
android:layout_gravity="center"/>
</FrameLayout>
<FrameLayout
android:id="@+id/avatar_color"
android:layout_width="@dimen/avatar_image_size_normal"
android:layout_height="@dimen/avatar_image_size_normal"
android:layout_gravity="center"
>
<ImageView
android:id="@+id/avatar_img"
android:layout_width="@dimen/avatar_image_size_normal"
android:layout_height="@dimen/avatar_image_size_normal"
android:src="@drawable/ic_default_avatar"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/avatar_initials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="@dimen/avatar_text_size_normal"
/>
</FrameLayout>
<ImageView
android:id="@+id/avatar_img"
android:layout_width="@dimen/avatar_image_size_normal"
android:layout_height="@dimen/avatar_image_size_normal"
android:scaleType="centerInside"
android:src="@drawable/ic_default_avatar"
/>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?attr/colorPrimaryDark">
android:background="?attr/colorPrimaryDark"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@color/white"
android:minWidth="288dp"
android:orientation="horizontal"
android:padding="@dimen/margin_24"
>
<LinearLayout
android:layout_width="wrap_content"
android:minWidth="288dp"
android:layout_width="0px"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/white"
android:padding="@dimen/margin_24"
android:layout_gravity="center">
<LinearLayout
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hostname"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"/>
<EditText
android:id="@+id/editor_hostname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:hint="demo.rocket.chat"
android:imeOptions="actionGo"
android:inputType="textWebEditText"/>
</LinearLayout>
android:layout_weight="1"
android:orientation="vertical"
>
<Space
android:layout_width="@dimen/margin_8"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hostname"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/btn_connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
app:srcCompat="@drawable/ic_arrow_forward_white_24dp"
app:elevation="2dp"
android:layout_gravity="end|bottom"/>
<EditText
android:id="@+id/editor_hostname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="demo.rocket.chat"
android:imeOptions="actionGo"
android:inputType="textWebEditText"
android:singleLine="true"
/>
</LinearLayout>
<Space
android:layout_width="@dimen/margin_8"
android:layout_height="wrap_content"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/btn_connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:elevation="2dp"
app:fabSize="mini"
app:srcCompat="@drawable/ic_arrow_forward_white_24dp"
/>
</LinearLayout>
</FrameLayout>
\ No newline at end of file
......@@ -2,10 +2,12 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimaryDark">
android:background="?attr/colorPrimaryDark"
>
<chat.rocket.android.view.WaitingView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<chat.rocket.android.view.WaitingView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="288dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="?attr/colorPrimary"
android:orientation="vertical"
android:theme="@style/AppTheme.Dark">
android:theme="@style/AppTheme.Dark"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/user_info_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/colorPrimaryDark">
<LinearLayout
android:id="@+id/user_info_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="@dimen/margin_16"
android:background="?attr/selectableItemBackground">
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="@dimen/margin_16"
>
<ImageView
android:id="@+id/img_userstatus"
android:layout_width="8dp"
android:layout_height="8dp"
android:src="@drawable/userstatus_online"/>
<ImageView
android:id="@+id/img_userstatus"
android:layout_width="8dp"
android:layout_height="8dp"
android:src="@drawable/userstatus_online"
/>
<Space
android:layout_width="@dimen/margin_8"
android:layout_height="wrap_content"/>
<Space
android:layout_width="@dimen/margin_8"
android:layout_height="wrap_content"
/>
<include layout="@layout/avatar_container_large"/>
<include layout="@layout/avatar_container_large"/>
<FrameLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="@dimen/margin_8"
android:layout_marginRight="@dimen/margin_8">
<FrameLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_8"
android:layout_marginRight="@dimen/margin_8"
android:layout_weight="1"
>
<TextView
android:id="@+id/txt_account_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_gravity="center_vertical"
android:text="John Doe"/>
<TextView
android:id="@+id/txt_account_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="John Doe"
android:textSize="14sp"
/>
</FrameLayout>
</FrameLayout>
<chat.rocket.android.view.FontAwesomeTextView
android:id="@+id/img_user_action_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fa_chevron_down"
android:textSize="16dp"/>
<chat.rocket.android.view.FontAwesomeTextView
android:id="@+id/img_user_action_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fa_chevron_down"
android:textSize="16dp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
......@@ -2,6 +2,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#00426B</color>
<color name="colorPrimaryDark">#FF001E31</color>
<color name="colorAccent">#FF2D91FA</color>
<color name="colorAccentLight">#FF6CB1FA</color>
<color name="colorAccentDark">#FF287DD7</color>
<color name="colorAccent_a40">#662D91FA</color>
<color name="textColorLink">#008ce3</color>
<color name="colorPrimary">#00426B</color>
<color name="colorPrimaryDark">#FF001E31</color>
<color name="colorAccent">#FF2D91FA</color>
<color name="colorAccentLight">#FF6CB1FA</color>
<color name="colorAccentDark">#FF287DD7</color>
<color name="colorAccent_a40">#662D91FA</color>
<color name="textColorLink">#008ce3</color>
<color name="divider">#FFEEEEEE</color>
<color name="divider">#FFEEEEEE</color>
<color name="white">#FFFEFEFF</color>
<color name="white">#FFFEFEFF</color>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="avatar_image_size_normal">24dp</dimen>
<dimen name="avatar_image_size_large">48dp</dimen>
<dimen name="avatar_text_size_normal">11sp</dimen>
<dimen name="avatar_text_size_large">28sp</dimen>
<dimen name="avatar_image_size_normal">24dp</dimen>
<dimen name="avatar_image_size_large">48dp</dimen>
<dimen name="avatar_text_size_normal">11sp</dimen>
<dimen name="avatar_text_size_large">28sp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string translatable="false" name="fa_chevron_down">&#xf078;</string>
<string name="fa_chevron_down" translatable="false">&#xf078;</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="margin_8">8dp</dimen>
<dimen name="margin_16">16dp</dimen>
<dimen name="margin_24">24dp</dimen>
<dimen name="margin_8">8dp</dimen>
<dimen name="margin_16">16dp</dimen>
<dimen name="margin_24">24dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">Rocket.Chat.Android</string>
<string name="app_name">Rocket.Chat.Android</string>
</resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
<item name="actionModeBackground">?attr/colorPrimaryDark</item>
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
<item name="android:navigationBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
</style>
<style name="AppTheme.Dark" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
<item name="actionModeBackground">?attr/colorPrimaryDark</item>
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
<item name="android:navigationBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
</style>
<style name="AppTheme.Dialog" parent="Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
<item name="actionModeBackground">?attr/colorPrimaryDark</item>
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
<item name="android:navigationBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
</style>
<style name="AppTheme.Dark" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
<item name="actionModeBackground">?attr/colorPrimaryDark</item>
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
<item name="android:navigationBarColor" tools:targetApi="21">?attr/colorPrimaryDark</item>
</style>
<style name="AppTheme.Dialog" parent="Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorLink">@drawable/selector_text_color_link</item>
<item name="android:listDivider">@color/divider</item>
<item name="colorControlActivated">@color/colorAccentDark</item>
<item name="android:textColorHighlight">@color/colorAccent_a40</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="userstatus_online">#35ac19</color>
<color name="userstatus_online_outline">#2c9210</color>
<color name="userstatus_away">#fcb316</color>
<color name="userstatus_away_outline">#e69200</color>
<color name="userstatus_busy">#d30230</color>
<color name="userstatus_busy_outline">#9f0030</color>
<color name="userstatus_offline">#7b7b7b</color>
<color name="userstatus_offline_outline">#666</color>
<color name="userstatus_online">#35ac19</color>
<color name="userstatus_online_outline">#2c9210</color>
<color name="userstatus_away">#fcb316</color>
<color name="userstatus_away_outline">#e69200</color>
<color name="userstatus_busy">#d30230</color>
<color name="userstatus_busy_outline">#9f0030</color>
<color name="userstatus_offline">#7b7b7b</color>
<color name="userstatus_offline_outline">#666</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WaitingView">
<attr name="dotSize" format="dimension" />
<attr name="dotCount" format="integer" />
</declare-styleable>
<dimen name="def_waiting_view_dot_size">16dp</dimen>
<declare-styleable name="WaitingView">
<attr format="dimension" name="dotSize"/>
<attr format="integer" name="dotCount"/>
</declare-styleable>
<dimen name="def_waiting_view_dot_size">16dp</dimen>
</resources>
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'me.tatarka:gradle-retrolambda:3.3.1'
classpath "io.realm:realm-gradle-plugin:2.1.1"
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
}
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'me.tatarka:gradle-retrolambda:3.3.1'
classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
classpath "io.realm:realm-gradle-plugin:2.1.1"
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
}
// Exclude the version that the android plugin depends on.
configurations.classpath.exclude group: 'com.android.tools.external.lombok'
}
allprojects {
repositories {
jcenter()
}
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
delete rootProject.buildDir
}
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<!-- suppress some checks for classes extending RealmObject -->
<suppress checks="JavadocMethod" files="chat[\\/]rocket[\\/]android[\\/]model"/>
</suppressions>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<Class name="~.*\.R\$.*"/>
</Match>
<Match>
<Class name="~.*\.Manifest\$.*"/>
</Match>
<!-- All bugs in test classes, except for JUnit-specific bugs -->
<Match>
<Class name="~.*\.*Test" />
<Not>
<Bug code="IJU" />
</Not>
</Match>
<Match>
<Class name="~.*\.R\$.*"/>
</Match>
<Match>
<Class name="~.*\.Manifest\$.*"/>
</Match>
<!-- All bugs in test classes, except for JUnit-specific bugs -->
<Match>
<Class name="~.*\.*Test"/>
<Not>
<Bug code="IJU"/>
</Not>
</Match>
</FindBugsFilter>
\ No newline at end of file
......@@ -4,25 +4,25 @@
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Custom ruleset for Rocket.Chat.Android application</description>
<description>Custom ruleset for Rocket.Chat.Android application</description>
<exclude-pattern>.*/R.java</exclude-pattern>
<exclude-pattern>.*/gen/.*</exclude-pattern>
<exclude-pattern>.*/R.java</exclude-pattern>
<exclude-pattern>.*/gen/.*</exclude-pattern>
<rule ref="rulesets/java/android.xml" />
<rule ref="rulesets/java/clone.xml" />
<rule ref="rulesets/java/finalizers.xml" />
<rule ref="rulesets/java/imports.xml">
<!-- Espresso is designed this way !-->
<exclude name="TooManyStaticImports" />
</rule>
<rule ref="rulesets/java/basic.xml" />
<rule ref="rulesets/java/naming.xml">
<!--<exclude name="AbstractNaming" />-->
<exclude name="LongVariable" />
<!--<exclude name="ShortMethodName" />-->
<!--<exclude name="ShortVariable" />-->
<!--<exclude name="ShortClassName" />-->
<!--<exclude name="VariableNamingConventions" />-->
</rule>
<rule ref="rulesets/java/android.xml"/>
<rule ref="rulesets/java/clone.xml"/>
<rule ref="rulesets/java/finalizers.xml"/>
<rule ref="rulesets/java/imports.xml">
<!-- Espresso is designed this way !-->
<exclude name="TooManyStaticImports"/>
</rule>
<rule ref="rulesets/java/basic.xml"/>
<rule ref="rulesets/java/naming.xml">
<!--<exclude name="AbstractNaming" />-->
<exclude name="LongVariable"/>
<!--exclude name="ShortMethodName" /-->
<!--exclude name="ShortVariable" /-->
<!--<exclude name="ShortClassName" />-->
<!--<exclude name="VariableNamingConventions" />-->
</rule>
</ruleset>
\ No newline at end of file
......@@ -7,15 +7,14 @@
* - pmd
*
* The three tasks above are added as dependencies of the check task so running check will
* run all of them.
*/
* run all of them.*/
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
dependencies {
checkstyle 'com.puppycrawl.tools:checkstyle:7.2'
checkstyle 'com.puppycrawl.tools:checkstyle:7.2'
}
def qualityConfigDir = "$project.rootDir/config/quality";
......@@ -24,67 +23,67 @@ def reportsDir = "$project.buildDir/reports"
check.dependsOn 'checkstyle', 'findbugs', 'pmd'
task checkstyle(type: Checkstyle, group: 'Verification', description: 'Runs code style checks') {
configFile file("$qualityConfigDir/checkstyle/checkstyle-config.xml")
source 'src'
include '**/*.java'
reports {
xml.enabled = true
xml {
destination "$reportsDir/checkstyle/checkstyle.xml"
}
configFile file("$qualityConfigDir/checkstyle/checkstyle-config.xml")
source 'src'
include '**/*.java'
reports {
xml.enabled = true
xml {
destination "$reportsDir/checkstyle/checkstyle.xml"
}
}
classpath = files( )
classpath = files()
}
task findbugs(type: FindBugs,
group: 'Verification',
description: 'Inspect java bytecode for bugs',
dependsOn: ['compileDebugSources','compileReleaseSources']) {
ignoreFailures = false
effort = "max"
reportLevel = "high"
excludeFilter = new File("$qualityConfigDir/findbugs/android-exclude-filter.xml")
classes = files("$project.rootDir/app/build/intermediates/classes")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = false
html.enabled = true
xml {
destination "$reportsDir/findbugs/findbugs.xml"
}
html {
destination "$reportsDir/findbugs/findbugs.html"
}
group: 'Verification',
description: 'Inspect java bytecode for bugs',
dependsOn: ['compileDebugSources', 'compileReleaseSources']) {
ignoreFailures = false
effort = "max"
reportLevel = "high"
excludeFilter = new File("$qualityConfigDir/findbugs/android-exclude-filter.xml")
classes = files("$project.rootDir/app/build/intermediates/classes")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = false
html.enabled = true
xml {
destination "$reportsDir/findbugs/findbugs.xml"
}
html {
destination "$reportsDir/findbugs/findbugs.html"
}
}
classpath = files()
classpath = files()
}
task pmd(type: Pmd, group: 'Verification', description: 'Inspect sourcecode for bugs') {
ruleSetFiles = files("$qualityConfigDir/pmd/pmd-ruleset.xml")
ignoreFailures = false
ruleSets = []
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = true
html.enabled = true
xml {
destination "$reportsDir/pmd/pmd.xml"
}
html {
destination "$reportsDir/pmd/pmd.html"
}
ruleSetFiles = files("$qualityConfigDir/pmd/pmd-ruleset.xml")
ignoreFailures = false
ruleSets = []
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = true
html.enabled = true
xml {
destination "$reportsDir/pmd/pmd.xml"
}
html {
destination "$reportsDir/pmd/pmd.html"
}
}
}
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
......
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