Skip to content
Snippets Groups Projects
Commit f16b99cf authored by John Carlson's avatar John Carlson
Browse files

Merge branch 'develop'

parents 2995603f eb7397c0
No related branches found
No related tags found
No related merge requests found
Pipeline #
Showing
with 857 additions and 705 deletions
Loading
@@ -41,6 +41,7 @@ The following 3rd party libraries and resources are the reason this app works. R
Loading
@@ -41,6 +41,7 @@ The following 3rd party libraries and resources are the reason this app works. R
- GitDiffTextView (https://github.com/alorma/GitDiffTextView) - GitDiffTextView (https://github.com/alorma/GitDiffTextView)
- MaterialDateTimePicker (https://github.com/wdullaer/MaterialDateTimePicker) - MaterialDateTimePicker (https://github.com/wdullaer/MaterialDateTimePicker)
- Crashlytics (https://www.crashlytics.com) - Crashlytics (https://www.crashlytics.com)
- highlight.js (https://highlightjs.org/)
   
## Contributing ## Contributing
Please fork this repository and contribute back! All Merge Requests should be made against the `develop` branch, as it is the active branch for development. Please make your best effort to break up commits as much as possible to improve the reviewing process. Please fork this repository and contribute back! All Merge Requests should be made against the `develop` branch, as it is the active branch for development. Please make your best effort to break up commits as much as possible to improve the reviewing process.
Loading
Loading
Loading
@@ -14,12 +14,12 @@ android {
Loading
@@ -14,12 +14,12 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 23 targetSdkVersion 23
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode 224 versionCode 225
versionName "2.2.4" versionName "2.2.5"
} }
buildTypes { buildTypes {
release { release {
minifyEnabled true minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
ext.enableCrashlytics = true ext.enableCrashlytics = true
manifestPlaceholders = [fabric_key: project.ext.LABCOAT_FABRIC_KEY] manifestPlaceholders = [fabric_key: project.ext.LABCOAT_FABRIC_KEY]
Loading
@@ -40,40 +40,56 @@ dependencies {
Loading
@@ -40,40 +40,56 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.0' testCompile 'org.robolectric:robolectric:3.0'
compile 'com.android.support:appcompat-v7:23.1.1' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
compile 'com.android.support:design:23.1.1' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:cardview-v7:23.1.1' compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:palette-v7:23.1.1' compile 'com.android.support:design:23.2.1'
compile 'com.android.support:customtabs:23.1.1' compile 'com.android.support:recyclerview-v7:23.2.1'
compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.android.support:cardview-v7:23.2.1'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' compile 'com.android.support:palette-v7:23.2.1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' compile 'com.android.support:customtabs:23.2.1'
compile ('com.squareup.retrofit:converter-simplexml:2.0.0-beta2') { compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile('com.squareup.retrofit2:converter-simplexml:2.0.0') {
exclude group: 'xpp3', module: 'xpp3' exclude group: 'xpp3', module: 'xpp3'
exclude group: 'stax', module: 'stax-api' exclude group: 'stax', module: 'stax-api'
exclude group: 'stax', module: 'stax' exclude group: 'stax', module: 'stax'
} }
compile 'com.squareup.okhttp:okhttp:2.7.2' compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
compile 'com.squareup:otto:1.3.8' compile 'com.squareup:otto:1.3.8'
compile 'io.reactivex:rxjava:1.1.2'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.jakewharton:butterknife:7.0.1' compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.jakewharton.timber:timber:4.1.0' compile 'com.jakewharton.timber:timber:4.1.1'
compile 'com.google.code.gson:gson:2.5' compile 'com.google.code.gson:gson:2.6.2'
compile 'net.danlew:android.joda:2.9.1' compile 'net.danlew:android.joda:2.9.2'
compile "org.parceler:parceler-api:1.0.3" compile "org.parceler:parceler-api:1.0.4"
apt "org.parceler:parceler:1.0.3" apt "org.parceler:parceler:1.0.4"
compile 'com.commit451:bypasses:1.0.1' compile 'com.commit451:bypasses:1.0.1'
compile 'com.commit451:easel:0.0.4' compile 'com.commit451:easel:0.0.5'
compile 'com.commit451:foregroundviews:1.0.0' compile 'com.commit451:foregroundviews:1.0.0'
compile 'com.commit451:elasticdragdismisslayout:1.0.2'
compile 'com.commit451:adapterlayout:1.0.1'
compile 'com.pnikosis:materialish-progress:1.7' compile 'com.pnikosis:materialish-progress:1.7'
compile 'com.jawnnypoo:physicslayout:1.0.1' compile 'com.jawnnypoo:physicslayout:1.0.1'
compile 'com.github.ivbaranov:MaterialLetterIcon:0.2.1' compile 'com.github.ivbaranov:materiallettericon:0.2.1'
compile 'com.github.johnkil.android-robototextview:robototextview:2.4.3' compile 'com.github.johnkil.android-robototextview:robototextview:2.5.0'
compile 'com.github.alorma:diff-textview:1.1.0' compile 'com.github.alorma:diff-textview:1.3.0'
compile 'com.wdullaer:materialdatetimepicker:2.1.1' compile 'com.wdullaer:materialdatetimepicker:2.3.0'
compile "com.wefika:flowlayout:0.4.1"
compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') { compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
transitive = true; transitive = true;
} }
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' compile('com.github.afollestad:app-theme-engine:1.0.1@aar') {
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' transitive = true
}
compile('com.github.afollestad.material-dialogs:core:0.8.5.7@aar') {
transitive = true
}
compile('com.github.afollestad.material-dialogs:commons:0.8.5.7@aar') {
transitive = true
}
} }
Loading
@@ -23,22 +23,25 @@
Loading
@@ -23,22 +23,25 @@
   
# So that Fabric can still have line numbers # So that Fabric can still have line numbers
-keepattributes SourceFile,LineNumberTable -keepattributes SourceFile,LineNumberTable
-keep class com.commit451.gitlab.ssl.CustomSSLSocketFactory
   
# Picasso rules # Picasso rules
-dontwarn com.squareup.okhttp.** -dontwarn com.squareup.okhttp.**
-dontwarn okhttp3.**
   
# Retrofit rules # Retrofit rules
-keep class com.squareup.okhttp.** { *; } -keep class okhttp3.** { *; }
-keep class retrofit.** { *; } -keep class retrofit2.** { *; }
-keep interface com.squareup.okhttp.** { *; } -keep interface okhttp3.** { *; }
   
-dontwarn com.squareup.okhttp.** -dontwarn com.squareup.okhttp.**
-dontwarn okhttp3.**
-dontwarn okio.** -dontwarn okio.**
-dontwarn retrofit.** -dontwarn retrofit2.**
-dontwarn rx.** -dontwarn rx.**
   
-keepclasseswithmembers class * { -keepclasseswithmembers class * {
@retrofit.http.* <methods>; @retrofit2.http.* <methods>;
} }
   
# If in your rest service interface you use methods with Callback argument. # If in your rest service interface you use methods with Callback argument.
Loading
Loading
Loading
@@ -30,11 +30,9 @@
Loading
@@ -30,11 +30,9 @@
<activity android:name=".activity.LoginActivity" /> <activity android:name=".activity.LoginActivity" />
   
<activity android:name=".activity.ProjectsActivity" <activity android:name=".activity.ProjectsActivity"
android:theme="@style/Activity.Projects"
android:launchMode="singleTask"/> android:launchMode="singleTask"/>
   
<activity android:name=".activity.GroupsActivity" <activity android:name=".activity.GroupsActivity"
android:theme="@style/Activity.Groups"
android:launchMode="singleTask"/> android:launchMode="singleTask"/>
   
<activity <activity
Loading
@@ -49,15 +47,14 @@
Loading
@@ -49,15 +47,14 @@
   
<activity android:name=".activity.AboutActivity"/> <activity android:name=".activity.AboutActivity"/>
<activity android:name=".activity.AddUserActivity"/> <activity android:name=".activity.AddUserActivity"/>
<activity android:name=".activity.UserActivity" <activity android:name=".activity.UserActivity"/>
android:theme="@style/Activity.User"/>
<activity android:name=".activity.SearchActivity"/> <activity android:name=".activity.SearchActivity"/>
<activity android:name=".activity.GroupActivity" <activity android:name=".activity.GroupActivity"/>
android:theme="@style/Activity.Group"/>
<activity android:name=".activity.MergeRequestActivity"/> <activity android:name=".activity.MergeRequestActivity"/>
<activity android:name=".activity.AddIssueActivity"/> <activity android:name=".activity.AddIssueActivity"/>
<activity android:name=".activity.MilestoneActivity"/> <activity android:name=".activity.MilestoneActivity"/>
<activity android:name=".activity.AddMilestoneActivity"/> <activity android:name=".activity.AddMilestoneActivity"/>
<activity android:name=".activity.SettingsActivity"/>
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="io.fabric.ApiKey"
android:value="${fabric_key}" /> android:value="${fabric_key}" />
Loading
Loading
Loading
@@ -4,124 +4,96 @@ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
Loading
@@ -4,124 +4,96 @@ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
   
*/ */
   
pre code { .hljs {
display: block; padding: 0.5em; display: block;
overflow-x: auto;
padding: 0.5em;
color: #333; color: #333;
background: #FFFFFF background: #f8f8f8;
} }
   
pre .comment, .hljs-comment,
pre .template_comment, .hljs-quote {
pre .diff .header,
pre .javadoc {
color: #998; color: #998;
font-style: italic font-style: italic;
} }
   
pre .keyword, .hljs-keyword,
pre .css .rule .keyword, .hljs-selector-tag,
pre .winutils, .hljs-subst {
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333; color: #333;
font-weight: bold font-weight: bold;
} }
   
pre .number, .hljs-number,
pre .hexcolor, .hljs-literal,
pre .ruby .constant { .hljs-variable,
color: #099; .hljs-template-variable,
.hljs-tag .hljs-attr {
color: #008080;
} }
   
pre .string, .hljs-string,
pre .tag .value, .hljs-doctag {
pre .phpdoc, color: #d14;
pre .tex .formula {
color: #d14
} }
   
pre .title, .hljs-title,
pre .id { .hljs-section,
.hljs-selector-id {
color: #900; color: #900;
font-weight: bold font-weight: bold;
} }
   
pre .javascript .title, .hljs-subst {
pre .lisp .title, font-weight: normal;
pre .clojure .title,
pre .subst {
font-weight: normal
} }
   
pre .class .title, .hljs-type,
pre .haskell .type, .hljs-class .hljs-title {
pre .vhdl .literal,
pre .tex .command {
color: #458; color: #458;
font-weight: bold font-weight: bold;
} }
   
pre .tag, .hljs-tag,
pre .tag .title, .hljs-name,
pre .rules .property, .hljs-attribute {
pre .django .tag .keyword {
color: #000080; color: #000080;
font-weight: normal font-weight: normal;
} }
   
pre .attribute, .hljs-regexp,
pre .variable, .hljs-link {
pre .lisp .body { color: #009926;
color: #008080
} }
   
pre .regexp { .hljs-symbol,
color: #009926 .hljs-bullet {
color: #990073;
} }
   
pre .class { .hljs-built_in,
color: #458; .hljs-builtin-name {
font-weight: bold color: #0086b3;
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
} }
   
pre .preprocessor, .hljs-meta {
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999; color: #999;
font-weight: bold font-weight: bold;
} }
   
pre .deletion { .hljs-deletion {
background: #fdd background: #fdd;
} }
   
pre .addition { .hljs-addition {
background: #dfd background: #dfd;
} }
   
pre .diff .change { .hljs-emphasis {
background: #0086b3 font-style: italic;
} }
   
pre .chunk { .hljs-strong {
color: #aaa font-weight: bold;
} }
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Loading
@@ -8,14 +8,17 @@ import android.hardware.SensorEventListener;
Loading
@@ -8,14 +8,17 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.Contributor; import com.commit451.gitlab.model.api.Contributor;
import com.commit451.gitlab.transformation.CircleTransformation; import com.commit451.gitlab.transformation.CircleTransformation;
Loading
@@ -34,9 +37,7 @@ import java.util.List;
Loading
@@ -34,9 +37,7 @@ import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
Loading
@@ -51,11 +52,15 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -51,11 +52,15 @@ public class AboutActivity extends BaseActivity {
return intent; return intent;
} }
   
@Bind(R.id.root) View root; @Bind(R.id.root)
@Bind(R.id.toolbar) Toolbar toolbar; ViewGroup mRoot;
@Bind(R.id.toolbar_title) TextView toolbarTitle; @Bind(R.id.toolbar)
@Bind(R.id.contributors) TextView contributors; Toolbar mToolbar;
@Bind(R.id.physics_layout) PhysicsFrameLayout physicsLayout; @Bind(R.id.contributors)
TextView mContributors;
@Bind(R.id.physics_layout)
PhysicsFrameLayout mPhysicsLayout;
@OnClick(R.id.sauce) @OnClick(R.id.sauce)
void onSauceClick() { void onSauceClick() {
if ("https://gitlab.com".equals(GitLabClient.getAccount().getServerUrl().toString())) { if ("https://gitlab.com".equals(GitLabClient.getAccount().getServerUrl().toString())) {
Loading
@@ -72,30 +77,28 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -72,30 +77,28 @@ public class AboutActivity extends BaseActivity {
@Override @Override
public void onSensorChanged(SensorEvent event) { public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GRAVITY) { if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
if (physicsLayout.getPhysics().getWorld() != null) { if (mPhysicsLayout.getPhysics().getWorld() != null) {
WindowUtil.normalizeForOrientation(getWindow(), event); WindowUtil.normalizeForOrientation(getWindow(), event);
physicsLayout.getPhysics().getWorld().setGravity(new Vec2(-event.values[0], event.values[1])); mPhysicsLayout.getPhysics().getWorld().setGravity(new Vec2(-event.values[0], event.values[1]));
} }
} }
} }
   
@Override @Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}; };
   
private Callback<List<Contributor>> mContributorResponseCallback = new Callback<List<Contributor>>() { private Callback<List<Contributor>> mContributorResponseCallback = new EasyCallback<List<Contributor>>() {
@Override @Override
public void onResponse(Response<List<Contributor>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Contributor> response) {
if (!response.isSuccess()) { addContributors(Contributor.groupContributors(response));
return;
}
addContributors(Contributor.groupContributors(response.body()));
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
Snackbar.make(getWindow().getDecorView(), R.string.failed_to_load_contributors, Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, R.string.failed_to_load_contributors, Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
Loading
@@ -106,15 +109,15 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -106,15 +109,15 @@ public class AboutActivity extends BaseActivity {
WindowUtil.lockToCurrentOrientation(this); WindowUtil.lockToCurrentOrientation(this);
setContentView(R.layout.activity_about); setContentView(R.layout.activity_about);
ButterKnife.bind(this); ButterKnife.bind(this);
toolbar.setNavigationIcon(R.drawable.ic_back_24dp); mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() { mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
onBackPressed(); onBackPressed();
} }
}); });
toolbarTitle.setText(R.string.about); mToolbar.setTitle(R.string.about);
physicsLayout.getPhysics().enableFling(); mPhysicsLayout.getPhysics().enableFling();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
GitLabClient.instance().getContributors(REPO_ID).enqueue(mContributorResponseCallback); GitLabClient.instance().getContributors(REPO_ID).enqueue(mContributorResponseCallback);
Loading
@@ -139,11 +142,10 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -139,11 +142,10 @@ public class AboutActivity extends BaseActivity {
.setFriction(0.0f) .setFriction(0.0f)
.setRestitution(0.0f) .setRestitution(0.0f)
.build(); .build();
int borderSize = getResources().getDimensionPixelSize(R.dimen.border_size);
int x = 0; int x = 0;
int y = 0; int y = 0;
int imageSize = getResources().getDimensionPixelSize(R.dimen.circle_size); int imageSize = getResources().getDimensionPixelSize(R.dimen.circle_size);
for (int i=0; i<contributors.size(); i++) { for (int i = 0; i < contributors.size(); i++) {
Contributor contributor = contributors.get(i); Contributor contributor = contributors.get(i);
ImageView imageView = new ImageView(this); ImageView imageView = new ImageView(this);
FrameLayout.LayoutParams llp = new FrameLayout.LayoutParams( FrameLayout.LayoutParams llp = new FrameLayout.LayoutParams(
Loading
@@ -151,14 +153,14 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -151,14 +153,14 @@ public class AboutActivity extends BaseActivity {
imageSize); imageSize);
imageView.setLayoutParams(llp); imageView.setLayoutParams(llp);
Physics.setPhysicsConfig(imageView, config); Physics.setPhysicsConfig(imageView, config);
physicsLayout.addView(imageView); mPhysicsLayout.addView(imageView);
imageView.setX(x); imageView.setX(x);
imageView.setY(y); imageView.setY(y);
   
x = (x + imageSize); x = (x + imageSize);
if (x > physicsLayout.getWidth()) { if (x > mPhysicsLayout.getWidth()) {
x = 0; x = 0;
y = (y + imageSize) % physicsLayout.getHeight(); y = (y + imageSize) % mPhysicsLayout.getHeight();
} }
   
Uri url = ImageUtil.getAvatarUrl(contributor.getEmail(), imageSize); Uri url = ImageUtil.getAvatarUrl(contributor.getEmail(), imageSize);
Loading
@@ -167,6 +169,6 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -167,6 +169,6 @@ public class AboutActivity extends BaseActivity {
.transform(new CircleTransformation()) .transform(new CircleTransformation())
.into(imageView); .into(imageView);
} }
physicsLayout.getPhysics().onLayout(true); mPhysicsLayout.getPhysics().onLayout(true);
} }
} }
Loading
@@ -3,20 +3,25 @@ package com.commit451.gitlab.activity;
Loading
@@ -3,20 +3,25 @@ package com.commit451.gitlab.activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Spinner; import android.widget.Spinner;
   
import com.afollestad.appthemeengine.customizers.ATEActivityThemeCustomizer;
import com.commit451.elasticdragdismisslayout.ElasticDragDismissFrameLayout;
import com.commit451.elasticdragdismisslayout.ElasticDragDismissListener;
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.AssigneeSpinnerAdapter; import com.commit451.gitlab.adapter.AssigneeSpinnerAdapter;
import com.commit451.gitlab.adapter.MilestoneSpinnerAdapter; import com.commit451.gitlab.adapter.MilestoneSpinnerAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.IssueChangedEvent; import com.commit451.gitlab.event.IssueChangedEvent;
import com.commit451.gitlab.event.IssueCreatedEvent; import com.commit451.gitlab.event.IssueCreatedEvent;
Loading
@@ -33,15 +38,19 @@ import java.util.List;
Loading
@@ -33,15 +38,19 @@ import java.util.List;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
* Activity to input new issues, but not really a dialog at all wink wink * Activity to input new issues, but not really a dialog at all wink wink
*/ */
public class AddIssueActivity extends MorphActivity { public class AddIssueActivity extends MorphActivity implements ATEActivityThemeCustomizer {
@Override
public int getActivityTheme() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", true) ?
R.style.Activity_Translucent : R.style.ActivityLight_Translucent;
}
   
private static final String KEY_PROJECT = "project"; private static final String KEY_PROJECT = "project";
private static final String KEY_ISSUE = "issue"; private static final String KEY_ISSUE = "issue";
Loading
@@ -55,31 +64,37 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -55,31 +64,37 @@ public class AddIssueActivity extends MorphActivity {
return intent; return intent;
} }
   
@Bind(R.id.root) ViewGroup mRoot; @Bind(R.id.root)
@Bind(R.id.toolbar) Toolbar mToolbar; ElasticDragDismissFrameLayout mRoot;
@Bind(R.id.title_text_input_layout) TextInputLayout mTitleInputLayout; @Bind(R.id.toolbar)
@Bind(R.id.title) EditText mTitleInput; Toolbar mToolbar;
@Bind(R.id.description) EditText mDescriptionInput; @Bind(R.id.title_text_input_layout)
@Bind(R.id.progress) View mProgress; TextInputLayout mTitleInputLayout;
@Bind(R.id.assignee_progress) View mAssigneeProgress; @Bind(R.id.title)
@Bind(R.id.assignee_spinner) Spinner mAssigneeSpinner; EditText mTitleInput;
@Bind(R.id.milestone_progress) View mMilestoneProgress; @Bind(R.id.description)
@Bind(R.id.milestone_spinner) Spinner mMilestoneSpinner; EditText mDescriptionInput;
@Bind(R.id.progress)
View mProgress;
@Bind(R.id.assignee_progress)
View mAssigneeProgress;
@Bind(R.id.assignee_spinner)
Spinner mAssigneeSpinner;
@Bind(R.id.milestone_progress)
View mMilestoneProgress;
@Bind(R.id.milestone_spinner)
Spinner mMilestoneSpinner;
   
private Project mProject; private Project mProject;
private Issue mIssue; private Issue mIssue;
private HashSet<Member> mMembers; private HashSet<Member> mMembers;
   
private final Callback<List<Milestone>> mMilestonesCallback = new Callback<List<Milestone>>() { private final Callback<List<Milestone>> mMilestonesCallback = new EasyCallback<List<Milestone>>() {
@Override @Override
public void onResponse(Response<List<Milestone>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Milestone> response) {
mMilestoneProgress.setVisibility(View.GONE); mMilestoneProgress.setVisibility(View.GONE);
if (!response.isSuccess()) {
mMilestoneSpinner.setVisibility(View.GONE);
return;
}
mMilestoneSpinner.setVisibility(View.VISIBLE); mMilestoneSpinner.setVisibility(View.VISIBLE);
MilestoneSpinnerAdapter milestoneSpinnerAdapter = new MilestoneSpinnerAdapter(AddIssueActivity.this, response.body()); MilestoneSpinnerAdapter milestoneSpinnerAdapter = new MilestoneSpinnerAdapter(AddIssueActivity.this, response);
mMilestoneSpinner.setAdapter(milestoneSpinnerAdapter); mMilestoneSpinner.setAdapter(milestoneSpinnerAdapter);
if (mIssue != null) { if (mIssue != null) {
mMilestoneSpinner.setSelection(milestoneSpinnerAdapter.getSelectedItemPosition(mIssue.getMilestone())); mMilestoneSpinner.setSelection(milestoneSpinnerAdapter.getSelectedItemPosition(mIssue.getMilestone()));
Loading
@@ -87,24 +102,17 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -87,24 +102,17 @@ public class AddIssueActivity extends MorphActivity {
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mMilestoneProgress.setVisibility(View.GONE); mMilestoneProgress.setVisibility(View.GONE);
mMilestoneSpinner.setVisibility(View.GONE); mMilestoneSpinner.setVisibility(View.GONE);
} }
}; };
   
private final Callback<List<Member>> mAssigneeCallback = new Callback<List<Member>>() { private final Callback<List<Member>> mAssigneeCallback = new EasyCallback<List<Member>>() {
@Override @Override
public void onResponse(Response<List<Member>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Member> response) {
if (!response.isSuccess()) { mMembers.addAll(response);
mAssigneeProgress.setVisibility(View.GONE);
mAssigneeSpinner.setVisibility(View.GONE);
return;
}
if (response.body() != null) {
mMembers.addAll(response.body());
}
if (mProject.belongsToGroup()) { if (mProject.belongsToGroup()) {
Timber.d("Project belongs to a group, loading those users too"); Timber.d("Project belongs to a group, loading those users too");
GitLabClient.instance().getGroupMembers(mProject.getNamespace().getId()).enqueue(mGroupMembersCallback); GitLabClient.instance().getGroupMembers(mProject.getNamespace().getId()).enqueue(mGroupMembersCallback);
Loading
@@ -114,55 +122,44 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -114,55 +122,44 @@ public class AddIssueActivity extends MorphActivity {
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mAssigneeSpinner.setVisibility(View.GONE); mAssigneeSpinner.setVisibility(View.GONE);
mAssigneeProgress.setVisibility(View.GONE); mAssigneeProgress.setVisibility(View.GONE);
} }
}; };
   
private final Callback<List<Member>> mGroupMembersCallback = new Callback<List<Member>>() { private final Callback<List<Member>> mGroupMembersCallback = new EasyCallback<List<Member>>() {
@Override @Override
public void onResponse(Response<List<Member>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Member> response) {
if (!response.isSuccess()) { mMembers.addAll(response);
mAssigneeSpinner.setVisibility(View.GONE);
return;
}
if (response.body() != null) {
mMembers.addAll(response.body());
}
setAssignees(); setAssignees();
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mAssigneeSpinner.setVisibility(View.GONE); mAssigneeSpinner.setVisibility(View.GONE);
mAssigneeProgress.setVisibility(View.GONE); mAssigneeProgress.setVisibility(View.GONE);
} }
}; };
   
private final Callback<Issue> mIssueCreatedCallback = new Callback<Issue>() { private final Callback<Issue> mIssueCreatedCallback = new EasyCallback<Issue>() {
   
@Override @Override
public void onResponse(Response<Issue> response, Retrofit retrofit) { public void onResponse(@NonNull Issue response) {
if (!response.isSuccess()) {
Snackbar.make(mRoot, getString(R.string.failed_to_create_issue), Snackbar.LENGTH_SHORT)
.show();
return;
}
if (mIssue == null) { if (mIssue == null) {
LabCoatApp.bus().post(new IssueCreatedEvent(response.body())); LabCoatApp.bus().post(new IssueCreatedEvent(response));
} else { } else {
LabCoatApp.bus().post(new IssueChangedEvent(response.body())); LabCoatApp.bus().post(new IssueChangedEvent(response));
} }
dismiss(); dismiss();
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
Snackbar.make(mRoot, getString(R.string.connection_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.failed_to_create_issue), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
Loading
@@ -205,6 +202,16 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -205,6 +202,16 @@ public class AddIssueActivity extends MorphActivity {
mToolbar.inflateMenu(R.menu.menu_add_milestone); mToolbar.inflateMenu(R.menu.menu_add_milestone);
} }
   
mRoot.addListener(new ElasticDragDismissListener() {
@Override
public void onDrag(float elasticOffset, float elasticOffsetPixels, float rawOffset, float rawOffsetPixels) {
}
@Override
public void onDragDismissed() {
onBackPressed();
}
});
load(); load();
} }
   
Loading
@@ -239,11 +246,11 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -239,11 +246,11 @@ public class AddIssueActivity extends MorphActivity {
} }
   
private void save() { private void save() {
if(!TextUtils.isEmpty(mTitleInput.getText())) { if (!TextUtils.isEmpty(mTitleInput.getText())) {
mTitleInputLayout.setError(null); mTitleInputLayout.setError(null);
showLoading(); showLoading();
Long assigneeId = null; Long assigneeId = null;
if (mAssigneeSpinner.getAdapter() != null ) { if (mAssigneeSpinner.getAdapter() != null) {
//the user did make a selection of some sort. So update it //the user did make a selection of some sort. So update it
Member member = (Member) mAssigneeSpinner.getSelectedItem(); Member member = (Member) mAssigneeSpinner.getSelectedItem();
if (member == null) { if (member == null) {
Loading
@@ -269,8 +276,7 @@ public class AddIssueActivity extends MorphActivity {
Loading
@@ -269,8 +276,7 @@ public class AddIssueActivity extends MorphActivity {
mDescriptionInput.getText().toString(), mDescriptionInput.getText().toString(),
assigneeId, assigneeId,
milestoneId); milestoneId);
} } else {
else {
mTitleInputLayout.setError(getString(R.string.required_field)); mTitleInputLayout.setError(getString(R.string.required_field));
} }
} }
Loading
Loading
Loading
@@ -4,6 +4,8 @@ package com.commit451.gitlab.activity;
Loading
@@ -4,6 +4,8 @@ package com.commit451.gitlab.activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
Loading
@@ -13,12 +15,17 @@ import android.view.View;
Loading
@@ -13,12 +15,17 @@ import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
   
import com.afollestad.appthemeengine.customizers.ATEActivityThemeCustomizer;
import com.commit451.elasticdragdismisslayout.ElasticDragDismissFrameLayout;
import com.commit451.elasticdragdismisslayout.ElasticDragDismissListener;
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.MilestoneChangedEvent; import com.commit451.gitlab.event.MilestoneChangedEvent;
import com.commit451.gitlab.event.MilestoneCreatedEvent; import com.commit451.gitlab.event.MilestoneCreatedEvent;
import com.commit451.gitlab.model.api.Milestone; import com.commit451.gitlab.model.api.Milestone;
import com.commit451.gitlab.util.AppThemeUtil;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
   
import org.parceler.Parcels; import org.parceler.Parcels;
Loading
@@ -29,12 +36,16 @@ import java.util.Date;
Loading
@@ -29,12 +36,16 @@ import java.util.Date;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
public class AddMilestoneActivity extends MorphActivity { public class AddMilestoneActivity extends MorphActivity implements ATEActivityThemeCustomizer {
@Override
public int getActivityTheme() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", true) ?
R.style.Activity_Translucent : R.style.ActivityLight_Translucent;
}
   
private static final String KEY_PROJECT_ID = "project_id"; private static final String KEY_PROJECT_ID = "project_id";
private static final String KEY_MILESTONE = "milestone"; private static final String KEY_MILESTONE = "milestone";
Loading
@@ -53,7 +64,7 @@ public class AddMilestoneActivity extends MorphActivity {
Loading
@@ -53,7 +64,7 @@ public class AddMilestoneActivity extends MorphActivity {
} }
   
@Bind(R.id.root) @Bind(R.id.root)
View mRoot; ElasticDragDismissFrameLayout mRoot;
@Bind(R.id.toolbar) @Bind(R.id.toolbar)
Toolbar mToolbar; Toolbar mToolbar;
@Bind(R.id.title_text_input_layout) @Bind(R.id.title_text_input_layout)
Loading
@@ -79,6 +90,7 @@ public class AddMilestoneActivity extends MorphActivity {
Loading
@@ -79,6 +90,7 @@ public class AddMilestoneActivity extends MorphActivity {
now.get(Calendar.MONTH), now.get(Calendar.MONTH),
now.get(Calendar.DAY_OF_MONTH) now.get(Calendar.DAY_OF_MONTH)
); );
dpd.setAccentColor(AppThemeUtil.resolveAccentColor(this));
dpd.show(getFragmentManager(), "date_picker"); dpd.show(getFragmentManager(), "date_picker");
} }
   
Loading
@@ -105,25 +117,21 @@ public class AddMilestoneActivity extends MorphActivity {
Loading
@@ -105,25 +117,21 @@ public class AddMilestoneActivity extends MorphActivity {
} }
}; };
   
private Callback<Milestone> mMilestoneCallback = new Callback<Milestone>() { private Callback<Milestone> mMilestoneCallback = new EasyCallback<Milestone>() {
   
@Override @Override
public void onResponse(Response<Milestone> response, Retrofit retrofit) { public void onResponse(@NonNull Milestone response) {
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
if (!response.isSuccess()) {
showError();
return;
}
if (mMilestone == null) { if (mMilestone == null) {
LabCoatApp.bus().post(new MilestoneCreatedEvent(response.body())); LabCoatApp.bus().post(new MilestoneCreatedEvent(response));
} else { } else {
LabCoatApp.bus().post(new MilestoneChangedEvent(response.body())); LabCoatApp.bus().post(new MilestoneChangedEvent(response));
} }
finish(); finish();
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
showError(); showError();
Loading
@@ -158,6 +166,15 @@ public class AddMilestoneActivity extends MorphActivity {
Loading
@@ -158,6 +166,15 @@ public class AddMilestoneActivity extends MorphActivity {
return false; return false;
} }
}); });
mRoot.addListener(new ElasticDragDismissListener() {
@Override
public void onDrag(float elasticOffset, float elasticOffsetPixels, float rawOffset, float rawOffsetPixels) {}
@Override
public void onDragDismissed() {
onBackPressed();
}
});
} }
   
private void createMilestone() { private void createMilestone() {
Loading
Loading
Loading
@@ -4,6 +4,7 @@ import android.content.Context;
Loading
@@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
Loading
@@ -14,13 +15,17 @@ import android.text.TextUtils;
Loading
@@ -14,13 +15,17 @@ import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.UsersAdapter; import com.commit451.gitlab.adapter.UsersAdapter;
import com.commit451.gitlab.animation.HideRunnable;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.api.exception.HttpException;
import com.commit451.gitlab.dialog.AccessDialog; import com.commit451.gitlab.dialog.AccessDialog;
import com.commit451.gitlab.event.MemberAddedEvent; import com.commit451.gitlab.event.MemberAddedEvent;
import com.commit451.gitlab.model.api.Group; import com.commit451.gitlab.model.api.Group;
Loading
@@ -37,9 +42,7 @@ import java.util.List;
Loading
@@ -37,9 +42,7 @@ import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
Loading
@@ -62,12 +65,18 @@ public class AddUserActivity extends MorphActivity {
Loading
@@ -62,12 +65,18 @@ public class AddUserActivity extends MorphActivity {
return intent; return intent;
} }
   
@Bind(R.id.root) View mRoot; @Bind(R.id.root)
@Bind(R.id.toolbar) Toolbar mToolbar; ViewGroup mRoot;
@Bind(R.id.search) EditText mUserSearch; @Bind(R.id.toolbar)
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout; Toolbar mToolbar;
@Bind(R.id.list) RecyclerView mRecyclerView; @Bind(R.id.search)
@Bind(R.id.clear) View mClearView; EditText mUserSearch;
@Bind(R.id.swipe_layout)
SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list)
RecyclerView mRecyclerView;
@Bind(R.id.clear)
View mClearView;
GridLayoutManager mUserLinearLayoutManager; GridLayoutManager mUserLinearLayoutManager;
   
@OnClick(R.id.clear) @OnClick(R.id.clear)
Loading
@@ -77,6 +86,7 @@ public class AddUserActivity extends MorphActivity {
Loading
@@ -77,6 +86,7 @@ public class AddUserActivity extends MorphActivity {
public void run() { public void run() {
mClearView.setVisibility(View.GONE); mClearView.setVisibility(View.GONE);
mUserSearch.getText().clear(); mUserSearch.getText().clear();
KeyboardUtil.showKeyboard(AddUserActivity.this, mUserSearch);
} }
}); });
} }
Loading
@@ -123,17 +133,15 @@ public class AddUserActivity extends MorphActivity {
Loading
@@ -123,17 +133,15 @@ public class AddUserActivity extends MorphActivity {
   
private final TextWatcher mTextWatcher = new TextWatcher() { private final TextWatcher mTextWatcher = new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
   
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
if (TextUtils.isEmpty(s)) { if (TextUtils.isEmpty(s)) {
mClearView.animate().alpha(0.0f).withEndAction(new Runnable() { mClearView.animate()
@Override .alpha(0.0f)
public void run() { .withEndAction(new HideRunnable(mClearView));
mClearView.setVisibility(View.GONE);
}
});
} else { } else {
mClearView.setVisibility(View.VISIBLE); mClearView.setVisibility(View.VISIBLE);
mClearView.animate().alpha(1.0f); mClearView.animate().alpha(1.0f);
Loading
@@ -141,49 +149,7 @@ public class AddUserActivity extends MorphActivity {
Loading
@@ -141,49 +149,7 @@ public class AddUserActivity extends MorphActivity {
} }
   
@Override @Override
public void afterTextChanged(Editable s) {} public void afterTextChanged(Editable s) {
};
private final Callback<List<UserBasic>> mUserCallback = new Callback<List<UserBasic>>() {
@Override
public void onResponse(Response<List<UserBasic>> response, Retrofit retrofit) {
mSwipeRefreshLayout.setRefreshing(false);
mLoading = false;
if (!response.isSuccess()) {
return;
}
mAdapter.setData(response.body());
mNextPageUrl = PaginationUtil.parse(response).getNext();
Timber.d("Next page url is %s", mNextPageUrl);
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
mLoading = false;
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error_users), Snackbar.LENGTH_SHORT)
.show();
}
};
private final Callback<List<UserBasic>> mMoreUsersCallback = new Callback<List<UserBasic>>() {
@Override
public void onResponse(Response<List<UserBasic>> response, Retrofit retrofit) {
mLoading = false;
mAdapter.setLoading(false);
if (!response.isSuccess()) {
return;
}
mAdapter.addData(response.body());
mNextPageUrl = PaginationUtil.parse(response).getNext();
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mAdapter.setLoading(false);
} }
}; };
   
Loading
@@ -213,27 +179,65 @@ public class AddUserActivity extends MorphActivity {
Loading
@@ -213,27 +179,65 @@ public class AddUserActivity extends MorphActivity {
} }
}; };
   
private final Callback<Member> mAddGroupMemeberCallback = new Callback<Member>() { private final Callback<List<UserBasic>> mUserCallback = new EasyCallback<List<UserBasic>>() {
@Override @Override
public void onResponse(Response<Member> response, Retrofit retrofit) { public void onResponse(@NonNull List<UserBasic> response) {
if (!response.isSuccess()) { mSwipeRefreshLayout.setRefreshing(false);
//Conflict mLoading = false;
if (response.code() == 409) { mAdapter.setData(response);
Snackbar.make(mRoot, R.string.error_user_conflict, Snackbar.LENGTH_SHORT) mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
.show(); Timber.d("Next page url is %s", mNextPageUrl);
} }
return;
} @Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
mLoading = false;
Snackbar.make(mRoot, getString(R.string.connection_error_users), Snackbar.LENGTH_SHORT)
.show();
}
};
private final Callback<List<UserBasic>> mMoreUsersCallback = new EasyCallback<List<UserBasic>>() {
@Override
public void onResponse(@NonNull List<UserBasic> response) {
mLoading = false;
mAdapter.setLoading(false);
mAdapter.addData(response);
mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mAdapter.setLoading(false);
}
};
private final Callback<Member> mAddGroupMemeberCallback = new EasyCallback<Member>() {
@Override
public void onResponse(@NonNull Member response) {
Snackbar.make(mRoot, R.string.user_added_successfully, Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, R.string.user_added_successfully, Snackbar.LENGTH_SHORT)
.show(); .show();
mAccessDialog.dismiss(); mAccessDialog.dismiss();
dismiss(); dismiss();
LabCoatApp.bus().post(new MemberAddedEvent(response.body())); LabCoatApp.bus().post(new MemberAddedEvent(response));
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
if (t instanceof HttpException) {
//Conflict
if (((HttpException) t).getCode() == 409) {
Snackbar.make(mRoot, R.string.error_user_conflict, Snackbar.LENGTH_SHORT)
.show();
}
} else {
Snackbar.make(mRoot, R.string.error_failed_to_add_user, Snackbar.LENGTH_SHORT)
.show();
}
} }
}; };
   
Loading
Loading
package com.commit451.gitlab.activity; package com.commit451.gitlab.activity;
   
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils; import android.text.TextUtils;
   
import com.afollestad.appthemeengine.ATEActivity;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
   
/** /**
* Created by Jawn on 7/27/2015. * Created by Jawn on 7/27/2015.
*/ */
public class BaseActivity extends AppCompatActivity { public class BaseActivity extends ATEActivity {
@Nullable
@Override
public final String getATEKey() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", true) ?
"dark_theme" : "light_theme";
}
   
public boolean hasEmptyFields(TextInputLayout... textInputLayouts) { public boolean hasEmptyFields(TextInputLayout... textInputLayouts) {
boolean hasEmptyField = false; boolean hasEmptyField = false;
Loading
Loading
Loading
@@ -3,16 +3,18 @@ package com.commit451.gitlab.activity;
Loading
@@ -3,16 +3,18 @@ package com.commit451.gitlab.activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar; import android.support.annotation.NonNull;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.DiffAdapter; import com.commit451.gitlab.adapter.DiffAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.Diff; import com.commit451.gitlab.model.api.Diff;
import com.commit451.gitlab.model.api.Project; import com.commit451.gitlab.model.api.Project;
Loading
@@ -24,9 +26,7 @@ import java.util.List;
Loading
@@ -24,9 +26,7 @@ import java.util.List;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
Loading
@@ -44,6 +44,7 @@ public class DiffActivity extends BaseActivity {
Loading
@@ -44,6 +44,7 @@ public class DiffActivity extends BaseActivity {
return intent; return intent;
} }
   
@Bind(R.id.root) ViewGroup mRoot;
@Bind(R.id.toolbar) Toolbar mToolbar; @Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout; @Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list) RecyclerView mDiffRecyclerView; @Bind(R.id.list) RecyclerView mDiffRecyclerView;
Loading
@@ -53,27 +54,19 @@ public class DiffActivity extends BaseActivity {
Loading
@@ -53,27 +54,19 @@ public class DiffActivity extends BaseActivity {
private Project mProject; private Project mProject;
private RepositoryCommit mCommit; private RepositoryCommit mCommit;
   
private Callback<List<Diff>> mDiffCallback = new Callback<List<Diff>>() { private Callback<List<Diff>> mDiffCallback = new EasyCallback<List<Diff>>() {
@Override @Override
public void onResponse(Response<List<Diff>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Diff> response) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
if (!response.isSuccess()) { mDiffAdapter.setData(response);
return;
}
for (Diff diff : response.body()) {
Timber.d("diff text: "+ diff.getDiff());
}
mDiffAdapter.setData(response.body());
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
Timber.e(t, null); Timber.e(t, null);
mMessageText.setText(R.string.connection_error); mMessageText.setText(R.string.connection_error);
mMessageText.setVisibility(View.VISIBLE); mMessageText.setVisibility(View.VISIBLE);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
} }
}; };
   
Loading
@@ -95,7 +88,7 @@ public class DiffActivity extends BaseActivity {
Loading
@@ -95,7 +88,7 @@ public class DiffActivity extends BaseActivity {
}); });
mToolbar.setTitle(mCommit.getShortId()); mToolbar.setTitle(mCommit.getShortId());
   
mDiffAdapter = new DiffAdapter(new DiffAdapter.Listener() { mDiffAdapter = new DiffAdapter(mCommit, new DiffAdapter.Listener() {
@Override @Override
public void onDiffClicked(Diff diff) { public void onDiffClicked(Diff diff) {
   
Loading
Loading
Loading
@@ -15,7 +15,6 @@ import android.support.design.widget.Snackbar;
Loading
@@ -15,7 +15,6 @@ import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.Html; import android.text.Html;
import android.util.Base64;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
Loading
@@ -23,8 +22,10 @@ import android.webkit.MimeTypeMap;
Loading
@@ -23,8 +22,10 @@ import android.webkit.MimeTypeMap;
import android.webkit.WebView; import android.webkit.WebView;
   
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.RepositoryFile; import com.commit451.gitlab.model.api.RepositoryFile;
import com.commit451.gitlab.observable.DecodeObservableFactory;
   
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
Loading
@@ -35,9 +36,10 @@ import java.nio.charset.Charset;
Loading
@@ -35,9 +36,10 @@ import java.nio.charset.Charset;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response; import rx.Subscriber;
import retrofit.Retrofit; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
   
public class FileActivity extends BaseActivity { public class FileActivity extends BaseActivity {
Loading
@@ -71,63 +73,23 @@ public class FileActivity extends BaseActivity {
Loading
@@ -71,63 +73,23 @@ public class FileActivity extends BaseActivity {
private long mProjectId; private long mProjectId;
private String mPath; private String mPath;
private String mRef; private String mRef;
private RepositoryFile mRepositoryFile;
private String mFileName; private String mFileName;
private byte[] mBlob; private byte[] mBlob;
private @Option int mOption; private @Option int mOption;
   
private final Callback<RepositoryFile> mFileResponseCallback = new Callback<RepositoryFile>() { private final Callback<RepositoryFile> mRepositoryFileCallback = new EasyCallback<RepositoryFile>() {
@Override @Override
public void onResponse(Response<RepositoryFile> response, Retrofit retrofit) { public void onResponse(@NonNull RepositoryFile response) {
mProgressView.setVisibility(View.GONE); mProgressView.setVisibility(View.GONE);
bindFile(response);
if (!response.isSuccess()) {
Snackbar.make(getWindow().getDecorView(), R.string.file_load_error, Snackbar.LENGTH_SHORT)
.show();
return;
}
if (response.body().getSize() > MAX_FILE_SIZE) {
Snackbar.make(getWindow().getDecorView(), R.string.file_too_big, Snackbar.LENGTH_SHORT)
.show();
return;
}
// Receiving side
mFileName = response.body().getFileName();
mBlob = Base64.decode(response.body().getContent(), Base64.DEFAULT);
String content;
String mimeType = null;
String extension = fileExt(mFileName);
if (extension != null) {
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mimeType != null) {
mimeType = mimeType.toLowerCase();
}
}
if (mimeType != null && mimeType.startsWith("image/")) {
String imageURL = "data:" + mimeType + ";base64," + response.body().getContent();
content = "<!DOCTYPE html><html><head><link href=\"github.css\" rel=\"stylesheet\" /></head><body><img style=\"width: 100%;\" src=\"" + imageURL + "\"></body></html>";
} else {
String text = new String(mBlob, Charset.forName("UTF-8"));
content = "<!DOCTYPE html><html><head><link href=\"github.css\" rel=\"stylesheet\" /></head><body><pre><code>" + Html.escapeHtml(text) + "</code></pre><script src=\"highlight.pack.js\"></script><script>hljs.initHighlightingOnLoad();</script></body></html>";
}
mFileBlobView.loadDataWithBaseURL("file:///android_asset/", content, "text/html", "utf8", null);
mToolbar.setTitle(mFileName);
mToolbar.inflateMenu(R.menu.file);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mProgressView.setVisibility(View.GONE); mProgressView.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), R.string.file_load_error, Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, R.string.file_load_error, Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
Loading
@@ -171,7 +133,83 @@ public class FileActivity extends BaseActivity {
Loading
@@ -171,7 +133,83 @@ public class FileActivity extends BaseActivity {
   
private void loadData() { private void loadData() {
mProgressView.setVisibility(View.VISIBLE); mProgressView.setVisibility(View.VISIBLE);
GitLabClient.instance().getFile(mProjectId, mPath, mRef).enqueue(mFileResponseCallback); GitLabClient.instance().getFile(mProjectId, mPath, mRef).enqueue(mRepositoryFileCallback);
}
private void bindFile(RepositoryFile repositoryFile) {
mRepositoryFile = repositoryFile;
mFileName = repositoryFile.getFileName();
mToolbar.setTitle(mFileName);
if (repositoryFile.getSize() > MAX_FILE_SIZE) {
Snackbar.make(mRoot, R.string.file_too_big, Snackbar.LENGTH_SHORT)
.show();
} else {
loadBlob(repositoryFile);
}
}
private void loadBlob(RepositoryFile repositoryFile) {
DecodeObservableFactory.newDecode(repositoryFile.getContent())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<byte[]>() {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {
Snackbar.make(mRoot, R.string.failed_to_load, Snackbar.LENGTH_SHORT)
.show();
}
@Override
public void onNext(byte[] bytes) {
bindBlob(bytes);
}
});
}
private void bindBlob(byte[] blob) {
mBlob = blob;
String content;
String mimeType = null;
String extension = fileExt(mFileName);
if (extension != null) {
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mimeType != null) {
mimeType = mimeType.toLowerCase();
}
}
if (mimeType != null && mimeType.startsWith("image/")) {
String imageURL = "data:" + mimeType + ";base64," + mRepositoryFile.getContent();
content = "<!DOCTYPE html>" +
"<html>" +
"<body>" +
"<img style=\"width: 100%;\" src=\"" + imageURL + "\">" +
"</body>" +
"</html>";
} else {
String text = new String(mBlob, Charset.forName("UTF-8"));
content = "<!DOCTYPE html>" +
"<html>" +
"<head>" +
"<link href=\"github.css\" rel=\"stylesheet\" />" +
"</head>" +
"<body>" +
"<pre><code>" +
Html.escapeHtml(text) +
"</code></pre>" +
"<script src=\"highlight.pack.js\"></script>" +
"<script>hljs.initHighlightingOnLoad();</script>" +
"</body>" +
"</html>";
}
mFileBlobView.loadDataWithBaseURL("file:///android_asset/", content, "text/html", "utf8", null);
mToolbar.inflateMenu(R.menu.menu_file);
} }
   
@TargetApi(23) @TargetApi(23)
Loading
@@ -213,13 +251,13 @@ public class FileActivity extends BaseActivity {
Loading
@@ -213,13 +251,13 @@ public class FileActivity extends BaseActivity {
outputStream = new FileOutputStream(targetFile); outputStream = new FileOutputStream(targetFile);
outputStream.write(mBlob); outputStream.write(mBlob);
   
Snackbar.make(getWindow().getDecorView(), getString(R.string.file_saved), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.file_saved), Snackbar.LENGTH_SHORT)
.show(); .show();
   
return targetFile; return targetFile;
} catch (IOException e) { } catch (IOException e) {
Timber.e(e, null); Timber.e(e, null);
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show(); .show();
} finally { } finally {
if (outputStream != null) { if (outputStream != null) {
Loading
@@ -231,7 +269,7 @@ public class FileActivity extends BaseActivity {
Loading
@@ -231,7 +269,7 @@ public class FileActivity extends BaseActivity {
} }
} }
} else { } else {
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
   
Loading
@@ -241,7 +279,7 @@ public class FileActivity extends BaseActivity {
Loading
@@ -241,7 +279,7 @@ public class FileActivity extends BaseActivity {
private void openFile() { private void openFile() {
File file = saveBlob(); File file = saveBlob();
if (file == null) { if (file == null) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show(); .show();
return; return;
} }
Loading
@@ -259,7 +297,7 @@ public class FileActivity extends BaseActivity {
Loading
@@ -259,7 +297,7 @@ public class FileActivity extends BaseActivity {
startActivity(intent); startActivity(intent);
} catch (ActivityNotFoundException | SecurityException e) { } catch (ActivityNotFoundException | SecurityException e) {
Timber.e(e, null); Timber.e(e, null);
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
} }
Loading
Loading
Loading
@@ -6,6 +6,8 @@ import android.os.Bundle;
Loading
@@ -6,6 +6,8 @@ import android.os.Bundle;
import com.commit451.gitlab.BuildConfig; import com.commit451.gitlab.BuildConfig;
import com.commit451.gitlab.data.Prefs; import com.commit451.gitlab.data.Prefs;
import com.commit451.gitlab.model.Account; import com.commit451.gitlab.model.Account;
import com.commit451.gitlab.util.AppThemeUtil;
import com.commit451.gitlab.ssl.CustomKeyManager;
import com.commit451.gitlab.util.NavigationManager; import com.commit451.gitlab.util.NavigationManager;
   
import java.util.List; import java.util.List;
Loading
@@ -20,6 +22,7 @@ public class GitlabActivity extends Activity {
Loading
@@ -20,6 +22,7 @@ public class GitlabActivity extends Activity {
   
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
AppThemeUtil.setupDefaultConfigs(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
   
int savedVersion = Prefs.getSavedVersion(this); int savedVersion = Prefs.getSavedVersion(this);
Loading
@@ -32,13 +35,44 @@ public class GitlabActivity extends Activity {
Loading
@@ -32,13 +35,44 @@ public class GitlabActivity extends Activity {
if(accounts.isEmpty()) { if(accounts.isEmpty()) {
NavigationManager.navigateToLogin(this); NavigationManager.navigateToLogin(this);
} else { } else {
NavigationManager.navigateToProjects(this); loadPrivateKey(accounts, 0);
return;
} }
   
// Always finish this activity // Always finish this activity
finish(); finish();
} }
   
private void loadPrivateKey(final List<Account> accounts, final int i) {
if (i >= accounts.size()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
NavigationManager.navigateToProjects(GitlabActivity.this);
finish();
}
});
return;
}
String alias = accounts.get(i).getPrivateKeyAlias();
if (alias != null && !CustomKeyManager.isCached(alias)) {
CustomKeyManager.cache(this, alias, new CustomKeyManager.KeyCallback() {
@Override
public void onSuccess(CustomKeyManager.KeyEntry entry) {
loadPrivateKey(accounts, i + 1);
}
@Override
public void onError(Exception e) {
loadPrivateKey(accounts, i + 1);
}
});
} else {
loadPrivateKey(accounts, i + 1);
}
}
/** /**
* Perform an upgrade from one version to another. This should only be one time upgrade things * Perform an upgrade from one version to another. This should only be one time upgrade things
*/ */
Loading
Loading
Loading
@@ -8,6 +8,8 @@ import android.graphics.Color;
Loading
@@ -8,6 +8,8 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
Loading
@@ -17,28 +19,36 @@ import android.support.v7.widget.Toolbar;
Loading
@@ -17,28 +19,36 @@ import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
   
import com.afollestad.appthemeengine.Config;
import com.afollestad.appthemeengine.customizers.ATEActivityThemeCustomizer;
import com.afollestad.appthemeengine.util.ATEUtil;
import com.commit451.easel.Easel; import com.commit451.easel.Easel;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.GroupPagerAdapter; import com.commit451.gitlab.adapter.GroupPagerAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.Group; import com.commit451.gitlab.model.api.Group;
import com.commit451.gitlab.model.api.GroupDetail; import com.commit451.gitlab.model.api.GroupDetail;
import com.commit451.gitlab.transformation.PaletteTransformation; import com.commit451.gitlab.transformation.PaletteTransformation;
import com.commit451.gitlab.util.AppThemeUtil;
   
import org.parceler.Parcels; import org.parceler.Parcels;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
* See the things about the group * See the things about the group
* Created by John on 10/14/15.
*/ */
public class GroupActivity extends BaseActivity { public class GroupActivity extends BaseActivity implements ATEActivityThemeCustomizer {
@Override
public int getActivityTheme() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", true) ?
R.style.Activity_Group : R.style.ActivityLight_Group;
}
   
private static final String KEY_GROUP = "key_group"; private static final String KEY_GROUP = "key_group";
private static final String KEY_GROUP_ID = "key_group_id"; private static final String KEY_GROUP_ID = "key_group_id";
Loading
@@ -62,18 +72,14 @@ public class GroupActivity extends BaseActivity {
Loading
@@ -62,18 +72,14 @@ public class GroupActivity extends BaseActivity {
@Bind(R.id.tabs) TabLayout mTabLayout; @Bind(R.id.tabs) TabLayout mTabLayout;
@Bind(R.id.backdrop) ImageView mBackdrop; @Bind(R.id.backdrop) ImageView mBackdrop;
   
private final Callback<GroupDetail> mGroupCallback = new Callback<GroupDetail>() { private final Callback<GroupDetail> mGroupCallback = new EasyCallback<GroupDetail>() {
@Override @Override
public void onResponse(Response<GroupDetail> response, Retrofit retrofit) { public void onResponse(@NonNull GroupDetail response) {
if (!response.isSuccess()) { bind(response);
showError();
return;
}
bind(response.body());
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
showError(); showError();
} }
Loading
@@ -85,6 +91,12 @@ public class GroupActivity extends BaseActivity {
Loading
@@ -85,6 +91,12 @@ public class GroupActivity extends BaseActivity {
setContentView(R.layout.activity_group); setContentView(R.layout.activity_group);
ButterKnife.bind(this); ButterKnife.bind(this);
   
// Default content and scrim colors
mCollapsingToolbarLayout.setContentScrimColor(
Config.primaryColor(this, AppThemeUtil.resolveThemeKey(this)));
mCollapsingToolbarLayout.setStatusBarScrimColor(
Config.primaryColorDark(this, AppThemeUtil.resolveThemeKey(this)));
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp); mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() { mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override @Override
Loading
@@ -127,8 +139,8 @@ public class GroupActivity extends BaseActivity {
Loading
@@ -127,8 +139,8 @@ public class GroupActivity extends BaseActivity {
   
private void bindPalette(Palette palette) { private void bindPalette(Palette palette) {
int animationTime = 1000; int animationTime = 1000;
int vibrantColor = palette.getVibrantColor(Easel.getThemeAttrColor(this, R.attr.colorPrimary)); int vibrantColor = palette.getVibrantColor(AppThemeUtil.resolvePrimaryColor(this));
int darkerColor = Easel.getDarkerColor(vibrantColor); int darkerColor = ATEUtil.darkenColor(vibrantColor);
   
if (Build.VERSION.SDK_INT >= 21) { if (Build.VERSION.SDK_INT >= 21) {
Easel.getNavigationBarColorAnimator(getWindow(), darkerColor) Easel.getNavigationBarColorAnimator(getWindow(), darkerColor)
Loading
Loading
Loading
@@ -4,6 +4,8 @@ import android.content.Context;
Loading
@@ -4,6 +4,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
Loading
@@ -14,8 +16,10 @@ import android.support.v7.widget.Toolbar;
Loading
@@ -14,8 +16,10 @@ import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
   
import com.afollestad.appthemeengine.customizers.ATEActivityThemeCustomizer;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.GroupAdapter; import com.commit451.gitlab.adapter.GroupAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.Group; import com.commit451.gitlab.model.api.Group;
import com.commit451.gitlab.util.NavigationManager; import com.commit451.gitlab.util.NavigationManager;
Loading
@@ -26,16 +30,20 @@ import java.util.List;
Loading
@@ -26,16 +30,20 @@ import java.util.List;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
* Displays the groups of the current user * Displays the groups of the current user
* Created by Jawn on 10/4/2015. * Created by Jawn on 10/4/2015.
*/ */
public class GroupsActivity extends BaseActivity { public class GroupsActivity extends BaseActivity implements ATEActivityThemeCustomizer {
@Override
public int getActivityTheme() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", true) ?
R.style.Activity_Groups : R.style.ActivityLight_Groups;
}
   
public static Intent newInstance(Context context) { public static Intent newInstance(Context context) {
Intent intent = new Intent(context, GroupsActivity.class); Intent intent = new Intent(context, GroupsActivity.class);
Loading
@@ -66,47 +74,42 @@ public class GroupsActivity extends BaseActivity {
Loading
@@ -66,47 +74,42 @@ public class GroupsActivity extends BaseActivity {
} }
}; };
   
private final Callback<List<Group>> mGroupsCallback = new Callback<List<Group>>() { private final Callback<List<Group>> mGroupsCallback = new EasyCallback<List<Group>>() {
@Override @Override
public void onResponse(Response<List<Group>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Group> response) {
mLoading = false; mLoading = false;
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
if (!response.isSuccess()) { if (response.isEmpty()) {
return;
}
if (response.body().isEmpty()) {
mMessageText.setText(R.string.no_groups); mMessageText.setText(R.string.no_groups);
mMessageText.setVisibility(View.VISIBLE); mMessageText.setVisibility(View.VISIBLE);
mGroupRecyclerView.setVisibility(View.GONE); mGroupRecyclerView.setVisibility(View.GONE);
} else { } else {
mGroupAdapter.setGroups(response.body()); mGroupAdapter.setGroups(response);
mMessageText.setVisibility(View.GONE); mMessageText.setVisibility(View.GONE);
mGroupRecyclerView.setVisibility(View.VISIBLE); mGroupRecyclerView.setVisibility(View.VISIBLE);
} }
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
mLoading = false; mLoading = false;
mMessageText.setVisibility(View.VISIBLE); mMessageText.setVisibility(View.VISIBLE);
mMessageText.setText(R.string.connection_error); mMessageText.setText(R.string.connection_error);
} }
}; };
   
private final Callback<List<Group>> mMoreGroupsCallback = new Callback<List<Group>>() { private final Callback<List<Group>> mMoreGroupsCallback = new EasyCallback<List<Group>>() {
@Override @Override
public void onResponse(Response<List<Group>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Group> response) {
mLoading = false; mLoading = false;
if (!response.isSuccess()) { mGroupAdapter.addGroups(response);
return; mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
}
mGroupAdapter.addGroups(response.body());
mNextPageUrl = PaginationUtil.parse(response).getNext();
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mLoading = false; mLoading = false;
} }
Loading
@@ -153,6 +156,7 @@ public class GroupsActivity extends BaseActivity {
Loading
@@ -153,6 +156,7 @@ public class GroupsActivity extends BaseActivity {
} }
   
private void load() { private void load() {
mMessageText.setVisibility(View.GONE);
mSwipeRefreshLayout.post(new Runnable() { mSwipeRefreshLayout.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Loading
Loading
Loading
@@ -4,6 +4,7 @@ import android.content.Context;
Loading
@@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
Loading
@@ -12,12 +13,14 @@ import android.support.v7.widget.Toolbar;
Loading
@@ -12,12 +13,14 @@ import android.support.v7.widget.Toolbar;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.IssueDetailsAdapter; import com.commit451.gitlab.adapter.IssueDetailsAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.IssueChangedEvent; import com.commit451.gitlab.event.IssueChangedEvent;
import com.commit451.gitlab.event.IssueReloadEvent; import com.commit451.gitlab.event.IssueReloadEvent;
Loading
@@ -37,9 +40,7 @@ import java.util.List;
Loading
@@ -37,9 +40,7 @@ import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
Loading
@@ -57,12 +58,20 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -57,12 +58,20 @@ public class IssueActivity extends BaseActivity {
return intent; return intent;
} }
   
@Bind(R.id.toolbar) Toolbar mToolbar; @Bind(R.id.root)
@Bind(R.id.issue_title) TextView mIssueTitle; ViewGroup mRoot;
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout; @Bind(R.id.toolbar)
@Bind(R.id.list) RecyclerView mNotesRecyclerView; Toolbar mToolbar;
@Bind(R.id.new_note_edit) EditText mNewNoteEdit; @Bind(R.id.issue_title)
@Bind(R.id.progress) View mProgress; TextView mIssueTitle;
@Bind(R.id.swipe_layout)
SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list)
RecyclerView mNotesRecyclerView;
@Bind(R.id.new_note_edit)
EditText mNewNoteEdit;
@Bind(R.id.progress)
View mProgress;
   
@OnClick(R.id.new_note_button) @OnClick(R.id.new_note_button)
public void onNewNoteClick() { public void onNewNoteClick() {
Loading
@@ -103,7 +112,7 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -103,7 +112,7 @@ public class IssueActivity extends BaseActivity {
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_share: case R.id.action_share:
IntentUtil.share(getWindow().getDecorView(), mIssue.getUrl(mProject)); IntentUtil.share(mRoot, mIssue.getUrl(mProject));
return true; return true;
case R.id.action_close: case R.id.action_close:
closeOrOpenIssue(); closeOrOpenIssue();
Loading
@@ -113,60 +122,49 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -113,60 +122,49 @@ public class IssueActivity extends BaseActivity {
} }
}; };
   
private Callback<List<Note>> mNotesCallback = new Callback<List<Note>>() { private Callback<List<Note>> mNotesCallback = new EasyCallback<List<Note>>() {
   
@Override @Override
public void onResponse(Response<List<Note>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Note> response) {
mLoading = false; mLoading = false;
if (!response.isSuccess()) {
return;
}
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
mNextPageUrl = PaginationUtil.parse(response).getNext(); mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
mIssueDetailsAdapter.setNotes(response.body()); mIssueDetailsAdapter.setNotes(response);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
mLoading = false; mLoading = false;
Timber.e(t, null); Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
   
private Callback<List<Note>> mMoreNotesCallback = new Callback<List<Note>>() { private Callback<List<Note>> mMoreNotesCallback = new EasyCallback<List<Note>>() {
   
@Override @Override
public void onResponse(Response<List<Note>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Note> response) {
mLoading = false; mLoading = false;
if (!response.isSuccess()) {
return;
}
mIssueDetailsAdapter.setLoading(false); mIssueDetailsAdapter.setLoading(false);
mNextPageUrl = PaginationUtil.parse(response).getNext(); mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
mIssueDetailsAdapter.addNotes(response.body()); mIssueDetailsAdapter.addNotes(response);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
mLoading = false; mLoading = false;
Timber.e(t, null); Timber.e(t, null);
mIssueDetailsAdapter.setLoading(false); mIssueDetailsAdapter.setLoading(false);
} }
}; };
   
private final Callback<Issue> mOpenCloseCallback = new Callback<Issue>() { private final Callback<Issue> mOpenCloseCallback = new EasyCallback<Issue>() {
@Override @Override
public void onResponse(Response<Issue> response, Retrofit retrofit) { public void onResponse(@NonNull Issue response) {
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
if (!response.isSuccess()) { mIssue = response;
Snackbar.make(getWindow().getDecorView(), getString(R.string.error_changing_issue), Snackbar.LENGTH_SHORT)
.show();
return;
}
mIssue = response.body();
LabCoatApp.bus().post(new IssueChangedEvent(mIssue)); LabCoatApp.bus().post(new IssueChangedEvent(mIssue));
LabCoatApp.bus().post(new IssueReloadEvent()); LabCoatApp.bus().post(new IssueReloadEvent());
setOpenCloseMenuStatus(); setOpenCloseMenuStatus();
Loading
@@ -174,31 +172,28 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -174,31 +172,28 @@ public class IssueActivity extends BaseActivity {
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), getString(R.string.error_changing_issue), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.error_changing_issue), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
   
private Callback<Note> mPostNoteCallback = new Callback<Note>() { private Callback<Note> mPostNoteCallback = new EasyCallback<Note>() {
   
@Override @Override
public void onResponse(Response<Note> response, Retrofit retrofit) { public void onResponse(@NonNull Note response) {
if (!response.isSuccess()) {
return;
}
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
mIssueDetailsAdapter.addNote(response.body()); mIssueDetailsAdapter.addNote(response);
mNotesRecyclerView.smoothScrollToPosition(IssueDetailsAdapter.getHeaderCount()); mNotesRecyclerView.smoothScrollToPosition(IssueDetailsAdapter.getHeaderCount());
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT) Snackbar.make(mRoot, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
Loading
@@ -222,7 +217,7 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -222,7 +217,7 @@ public class IssueActivity extends BaseActivity {
} }
}); });
mToolbar.setSubtitle(mProject.getNameWithNamespace()); mToolbar.setSubtitle(mProject.getNameWithNamespace());
mToolbar.inflateMenu(R.menu.issue); mToolbar.inflateMenu(R.menu.menu_issue);
mOpenCloseMenuItem = mToolbar.getMenu().findItem(R.id.action_close); mOpenCloseMenuItem = mToolbar.getMenu().findItem(R.id.action_close);
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener); mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
   
Loading
@@ -285,7 +280,7 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -285,7 +280,7 @@ public class IssueActivity extends BaseActivity {
private void postNote() { private void postNote() {
String body = mNewNoteEdit.getText().toString(); String body = mNewNoteEdit.getText().toString();
   
if(body.length() < 1) { if (body.length() < 1) {
return; return;
} }
   
Loading
@@ -303,7 +298,7 @@ public class IssueActivity extends BaseActivity {
Loading
@@ -303,7 +298,7 @@ public class IssueActivity extends BaseActivity {
mProgress.setVisibility(View.VISIBLE); mProgress.setVisibility(View.VISIBLE);
if (mIssue.getState() == Issue.State.CLOSED) { if (mIssue.getState() == Issue.State.CLOSED) {
GitLabClient.instance().updateIssueStatus(mProject.getId(), mIssue.getId(), Issue.STATE_REOPEN) GitLabClient.instance().updateIssueStatus(mProject.getId(), mIssue.getId(), Issue.STATE_REOPEN)
.enqueue(mOpenCloseCallback); .enqueue(mOpenCloseCallback);
} else { } else {
GitLabClient.instance().updateIssueStatus(mProject.getId(), mIssue.getId(), Issue.STATE_CLOSE) GitLabClient.instance().updateIssueStatus(mProject.getId(), mIssue.getId(), Issue.STATE_CLOSE)
.enqueue(mOpenCloseCallback); .enqueue(mOpenCloseCallback);
Loading
Loading
package com.commit451.gitlab.activity; package com.commit451.gitlab.activity;
   
import android.Manifest; import android.Manifest;
import android.accounts.AccountManager;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
Loading
@@ -10,13 +11,19 @@ import android.content.Intent;
Loading
@@ -10,13 +11,19 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.util.Patterns;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
Loading
@@ -29,55 +36,81 @@ import com.commit451.gitlab.event.ReloadDataEvent;
Loading
@@ -29,55 +36,81 @@ import com.commit451.gitlab.event.ReloadDataEvent;
import com.commit451.gitlab.model.Account; import com.commit451.gitlab.model.Account;
import com.commit451.gitlab.model.api.UserFull; import com.commit451.gitlab.model.api.UserFull;
import com.commit451.gitlab.model.api.UserLogin; import com.commit451.gitlab.model.api.UserLogin;
import com.commit451.gitlab.ssl.CustomHostnameVerifier;
import com.commit451.gitlab.ssl.CustomKeyManager;
import com.commit451.gitlab.ssl.X509CertificateException; import com.commit451.gitlab.ssl.X509CertificateException;
import com.commit451.gitlab.ssl.X509Util; import com.commit451.gitlab.ssl.X509Util;
import com.commit451.gitlab.util.KeyboardUtil; import com.commit451.gitlab.util.KeyboardUtil;
import com.commit451.gitlab.util.NavigationManager; import com.commit451.gitlab.util.NavigationManager;
import com.commit451.gitlab.view.EmailAutoCompleteTextView;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.HttpUrl;
   
import java.net.ConnectException;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
   
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import okhttp3.Credentials;
import retrofit.Response; import okhttp3.HttpUrl;
import retrofit.Retrofit; import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import timber.log.Timber; import timber.log.Timber;
   
public class LoginActivity extends BaseActivity { public class LoginActivity extends BaseActivity {
   
private static final String EXTRA_SHOW_CLOSE = "show_close";
private static final int PERMISSION_REQUEST_GET_ACCOUNTS = 1337; private static final int PERMISSION_REQUEST_GET_ACCOUNTS = 1337;
private static Pattern sTokenPattern = Pattern.compile("^[A-Za-z0-9-_]*$"); private static Pattern sTokenPattern = Pattern.compile("^[A-Za-z0-9-_]*$");
   
public static Intent newInstance(Context context) { public static Intent newInstance(Context context) {
return newInstance(context, false);
}
public static Intent newInstance(Context context, boolean showClose) {
Intent intent = new Intent(context, LoginActivity.class); Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra(EXTRA_SHOW_CLOSE, showClose);
return intent; return intent;
} }
   
@Bind(R.id.root) View mRoot; @Bind(R.id.root)
@Bind(R.id.url_hint) TextInputLayout mUrlHint; View mRoot;
@Bind(R.id.url_input) TextView mUrlInput; @Bind(R.id.close)
@Bind(R.id.user_input_hint) TextInputLayout mUserHint; View mClose;
@Bind(R.id.user_input) EmailAutoCompleteTextView mUserInput; @Bind(R.id.url_hint)
@Bind(R.id.password_hint) TextInputLayout mPasswordHint; TextInputLayout mUrlHint;
@Bind(R.id.password_input) TextView mPasswordInput; @Bind(R.id.url_input)
@Bind(R.id.token_hint) TextInputLayout mTokenHint; TextView mUrlInput;
@Bind(R.id.token_input) TextView mTokenInput; @Bind(R.id.user_input_hint)
@Bind(R.id.normal_login) View mNormalLogin; TextInputLayout mUserHint;
@Bind(R.id.token_login) View mTokenLogin; @Bind(R.id.user_input)
@Bind(R.id.progress) View mProgress; AppCompatAutoCompleteTextView mUserInput;
@Bind(R.id.password_hint)
TextInputLayout mPasswordHint;
@Bind(R.id.password_input)
TextView mPasswordInput;
@Bind(R.id.token_hint)
TextInputLayout mTokenHint;
@Bind(R.id.token_input)
TextView mTokenInput;
@Bind(R.id.normal_login)
View mNormalLogin;
@Bind(R.id.token_login)
View mTokenLogin;
@Bind(R.id.progress)
View mProgress;
   
private boolean mIsNormalLogin = true; private boolean mIsNormalLogin = true;
private String mTrustedCertificate;
private String mAuthorizationHeader;
private Account mAccount; private Account mAccount;
   
private final TextView.OnEditorActionListener onEditorActionListener = new TextView.OnEditorActionListener() { private final TextView.OnEditorActionListener onEditorActionListener = new TextView.OnEditorActionListener() {
Loading
@@ -88,6 +121,11 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -88,6 +121,11 @@ public class LoginActivity extends BaseActivity {
} }
}; };
   
@OnClick(R.id.close)
public void onCloseClick() {
onBackPressed();
}
@OnClick(R.id.show_normal_link) @OnClick(R.id.show_normal_link)
public void showNormalLogin(TextView loginTypeTextView) { public void showNormalLogin(TextView loginTypeTextView) {
if (mNormalLogin.getVisibility() == View.VISIBLE) { if (mNormalLogin.getVisibility() == View.VISIBLE) {
Loading
@@ -152,8 +190,21 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -152,8 +190,21 @@ public class LoginActivity extends BaseActivity {
   
mAccount = new Account(); mAccount = new Account();
mAccount.setServerUrl(uri); mAccount.setServerUrl(uri);
mAccount.setTrustedCertificate(mTrustedCertificate);
mAccount.setAuthorizationHeader(mAuthorizationHeader); login();
}
private void login() {
// This seems useless - But believe me, it makes everything work! Don't remove it.
// (OkHttpClientProvider caches the clients and needs a new account to recreate them)
Account newAccount = new Account();
newAccount.setServerUrl(mAccount.getServerUrl());
newAccount.setTrustedCertificate(mAccount.getTrustedCertificate());
newAccount.setTrustedHostname(mAccount.getTrustedHostname());
newAccount.setPrivateKeyAlias(mAccount.getPrivateKeyAlias());
newAccount.setAuthorizationHeader(mAccount.getAuthorizationHeader());
mAccount = newAccount;
   
if (mIsNormalLogin) { if (mIsNormalLogin) {
connect(true); connect(true);
Loading
@@ -162,32 +213,70 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -162,32 +213,70 @@ public class LoginActivity extends BaseActivity {
} }
} }
   
private void loginWithPrivateToken() {
KeyChain.choosePrivateKeyAlias(this, new KeyChainAliasCallback() {
@Override
public void alias(String alias) {
mAccount.setPrivateKeyAlias(alias);
if (alias != null) {
if (!CustomKeyManager.isCached(alias)) {
CustomKeyManager.cache(LoginActivity.this, alias, new CustomKeyManager.KeyCallback() {
@Override
public void onSuccess(CustomKeyManager.KeyEntry entry) {
runOnUiThread(new Runnable() {
@Override
public void run() {
login();
}
});
}
@Override
public void onError(Exception e) {
mAccount.setPrivateKeyAlias(null);
Timber.e(e, "Failed to load private key");
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
login();
}
});
}
}
}
}, null, null, mAccount.getServerUrl().getHost(), mAccount.getServerUrl().getPort(), null);
}
private Callback<UserLogin> mLoginCallback = new Callback<UserLogin>() { private Callback<UserLogin> mLoginCallback = new Callback<UserLogin>() {
   
@Override @Override
public void onResponse(Response<UserLogin> response, Retrofit retrofit) { public void onResponse(Call<UserLogin> call, Response<UserLogin> response) {
mTrustedCertificate = null; if (!response.isSuccessful()) {
if (!response.isSuccess()) {
handleConnectionResponse(response); handleConnectionResponse(response);
return; return;
} }
mAccount.setPrivateToken(response.body().getPrivateToken()); mAccount.setPrivateToken(response.body().getPrivateToken());
loadUser(); loadUser();
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Call<UserLogin> call, Throwable t) {
mTrustedCertificate = null;
Timber.e(t, null); Timber.e(t, null);
handleConnectionError(t); handleConnectionError(t);
} }
}; };
   
private Callback<UserFull> mTestUserCallback = new Callback<UserFull>() { private Callback<UserFull> mTestUserCallback = new Callback<UserFull>() {
@Override @Override
public void onResponse(Response<UserFull> response, Retrofit retrofit) { public void onResponse(Call<UserFull> call, Response<UserFull> response) {
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
if (!response.isSuccess()) { if (!response.isSuccessful()) {
handleConnectionResponse(response); handleConnectionResponse(response);
return; return;
} }
Loading
@@ -203,8 +292,7 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -203,8 +292,7 @@ public class LoginActivity extends BaseActivity {
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Call<UserFull> call, Throwable t) {
mTrustedCertificate = null;
Timber.e(t, null); Timber.e(t, null);
handleConnectionError(t); handleConnectionError(t);
} }
Loading
@@ -215,6 +303,10 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -215,6 +303,10 @@ public class LoginActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login); setContentView(R.layout.activity_login);
ButterKnife.bind(this); ButterKnife.bind(this);
boolean showClose = getIntent().getBooleanExtra(EXTRA_SHOW_CLOSE, false);
mClose.setVisibility(showClose ? View.VISIBLE : View.GONE);
mPasswordInput.setOnEditorActionListener(onEditorActionListener); mPasswordInput.setOnEditorActionListener(onEditorActionListener);
mTokenInput.setOnEditorActionListener(onEditorActionListener); mTokenInput.setOnEditorActionListener(onEditorActionListener);
mUserInput.setOnFocusChangeListener(new View.OnFocusChangeListener() { mUserInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
Loading
@@ -230,7 +322,7 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -230,7 +322,7 @@ public class LoginActivity extends BaseActivity {
@TargetApi(23) @TargetApi(23)
private void checkAccountPermission() { private void checkAccountPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED) {
mUserInput.retrieveAccounts(); retrieveAccounts();
} else { } else {
requestPermissions(new String[]{Manifest.permission.GET_ACCOUNTS}, PERMISSION_REQUEST_GET_ACCOUNTS); requestPermissions(new String[]{Manifest.permission.GET_ACCOUNTS}, PERMISSION_REQUEST_GET_ACCOUNTS);
} }
Loading
@@ -240,8 +332,8 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -240,8 +332,8 @@ public class LoginActivity extends BaseActivity {
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) { switch (requestCode) {
case PERMISSION_REQUEST_GET_ACCOUNTS: { case PERMISSION_REQUEST_GET_ACCOUNTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mUserInput.retrieveAccounts(); retrieveAccounts();
} }
} }
} }
Loading
@@ -252,19 +344,17 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -252,19 +344,17 @@ public class LoginActivity extends BaseActivity {
mProgress.setAlpha(0.0f); mProgress.setAlpha(0.0f);
mProgress.animate().alpha(1.0f); mProgress.animate().alpha(1.0f);
   
if(byAuth) { if (byAuth) {
connectByAuth(); connectByAuth();
} } else {
else {
connectByToken(); connectByToken();
} }
} }
   
private void connectByAuth() { private void connectByAuth() {
if(mUserInput.getText().toString().contains("@")) { if (mUserInput.getText().toString().contains("@")) {
GitLabClient.instance(mAccount).loginWithEmail(mUserInput.getText().toString(), mPasswordInput.getText().toString()).enqueue(mLoginCallback); GitLabClient.instance(mAccount).loginWithEmail(mUserInput.getText().toString(), mPasswordInput.getText().toString()).enqueue(mLoginCallback);
} } else {
else {
GitLabClient.instance(mAccount).loginWithUsername(mUserInput.getText().toString(), mPasswordInput.getText().toString()).enqueue(mLoginCallback); GitLabClient.instance(mAccount).loginWithUsername(mUserInput.getText().toString(), mPasswordInput.getText().toString()).enqueue(mLoginCallback);
} }
} }
Loading
@@ -281,7 +371,8 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -281,7 +371,8 @@ public class LoginActivity extends BaseActivity {
private void handleConnectionError(Throwable t) { private void handleConnectionError(Throwable t) {
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
   
if(t instanceof SSLHandshakeException && t.getCause() instanceof X509CertificateException) { if (t instanceof SSLHandshakeException && t.getCause() instanceof X509CertificateException) {
mAccount.setTrustedCertificate(null);
String fingerprint = null; String fingerprint = null;
try { try {
fingerprint = X509Util.getFingerPrint(((X509CertificateException) t.getCause()).getChain()[0]); fingerprint = X509Util.getFingerPrint(((X509CertificateException) t.getCause()).getChain()[0]);
Loading
@@ -297,8 +388,8 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -297,8 +388,8 @@ public class LoginActivity extends BaseActivity {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (finalFingerprint != null) { if (finalFingerprint != null) {
mTrustedCertificate = finalFingerprint; mAccount.setTrustedCertificate(finalFingerprint);
onLoginClick(); login();
} }
   
dialog.dismiss(); dialog.dismiss();
Loading
@@ -312,7 +403,36 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -312,7 +403,36 @@ public class LoginActivity extends BaseActivity {
}) })
.show(); .show();
   
((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); ((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
} else if (t instanceof SSLPeerUnverifiedException && t.getMessage().toLowerCase().contains("hostname")) {
mAccount.setTrustedHostname(null);
final String finalHostname = CustomHostnameVerifier.getLastFailedHostname();
Dialog d = new AlertDialog.Builder(this)
.setTitle(R.string.hostname_title)
.setMessage(R.string.hostname_message)
.setPositiveButton(R.string.ok_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (finalHostname != null) {
mAccount.setTrustedHostname(finalHostname);
login();
}
dialog.dismiss();
}
})
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
} else if (t instanceof ConnectException) {
Snackbar.make(mRoot, t.getLocalizedMessage(), Snackbar.LENGTH_LONG)
.show();
} else { } else {
Snackbar.make(mRoot, getString(R.string.login_error), Snackbar.LENGTH_LONG) Snackbar.make(mRoot, getString(R.string.login_error), Snackbar.LENGTH_LONG)
.show(); .show();
Loading
@@ -323,6 +443,8 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -323,6 +443,8 @@ public class LoginActivity extends BaseActivity {
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
switch (response.code()) { switch (response.code()) {
case 401: case 401:
mAccount.setAuthorizationHeader(null);
String header = response.headers().get("WWW-Authenticate"); String header = response.headers().get("WWW-Authenticate");
if (header != null) { if (header != null) {
handleBasicAuthentication(response); handleBasicAuthentication(response);
Loading
@@ -331,6 +453,9 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -331,6 +453,9 @@ public class LoginActivity extends BaseActivity {
Snackbar.make(mRoot, getString(R.string.login_unauthorized), Snackbar.LENGTH_LONG) Snackbar.make(mRoot, getString(R.string.login_unauthorized), Snackbar.LENGTH_LONG)
.show(); .show();
return; return;
case 404:
Snackbar.make(mRoot, getString(R.string.login_404_error), Snackbar.LENGTH_LONG)
.show();
default: default:
Snackbar.make(mRoot, getString(R.string.login_error), Snackbar.LENGTH_LONG) Snackbar.make(mRoot, getString(R.string.login_error), Snackbar.LENGTH_LONG)
.show(); .show();
Loading
@@ -355,13 +480,12 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -355,13 +480,12 @@ public class LoginActivity extends BaseActivity {
HttpLoginDialog dialog = new HttpLoginDialog(this, realm, new HttpLoginDialog.LoginListener() { HttpLoginDialog dialog = new HttpLoginDialog(this, realm, new HttpLoginDialog.LoginListener() {
@Override @Override
public void onLogin(String username, String password) { public void onLogin(String username, String password) {
mAuthorizationHeader = Credentials.basic(username, password); mAccount.setAuthorizationHeader(Credentials.basic(username, password));
onLoginClick(); login();
} }
   
@Override @Override
public void onCancel() { public void onCancel() {
mAuthorizationHeader = null;
} }
}); });
dialog.show(); dialog.show();
Loading
@@ -380,4 +504,35 @@ public class LoginActivity extends BaseActivity {
Loading
@@ -380,4 +504,35 @@ public class LoginActivity extends BaseActivity {
} }
return false; return false;
} }
/**
* Manually retrieve the accounts, typically used for API 23+ after getting the permission. Called automatically
* on creation, but needs to be recalled if the permission is granted later
*/
public void retrieveAccounts() {
Collection<String> accounts = getEmailAccounts();
if (accounts != null && !accounts.isEmpty()) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
R.layout.support_simple_spinner_dropdown_item,
new ArrayList<>(accounts));
mUserInput.setAdapter(adapter);
}
}
/**
* Get all the accounts that appear to be email accounts. HashSet so that we do not get duplicates
*
* @return list of email accounts
*/
private Set<String> getEmailAccounts() {
HashSet<String> emailAccounts = new HashSet<>();
AccountManager manager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
final android.accounts.Account[] accounts = manager.getAccounts();
for (android.accounts.Account account : accounts) {
if (!TextUtils.isEmpty(account.name) && Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
emailAccounts.add(account.name);
}
}
return emailAccounts;
}
} }
Loading
@@ -2,38 +2,22 @@ package com.commit451.gitlab.activity;
Loading
@@ -2,38 +2,22 @@ package com.commit451.gitlab.activity;
   
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar; import android.support.design.widget.TabLayout;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.view.ViewPager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.view.ViewGroup;
import android.widget.TextView;
   
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.MergeRequestDetailAdapter; import com.commit451.gitlab.adapter.MergeRequestSectionsPagerAdapter;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.MergeRequest; import com.commit451.gitlab.model.api.MergeRequest;
import com.commit451.gitlab.model.api.Note;
import com.commit451.gitlab.model.api.Project; import com.commit451.gitlab.model.api.Project;
import com.commit451.gitlab.util.KeyboardUtil;
import com.commit451.gitlab.util.PaginationUtil;
   
import org.parceler.Parcels; import org.parceler.Parcels;
   
import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
   
/** /**
* Shows the details of a merge request * Shows the details of a merge request
Loading
@@ -50,108 +34,17 @@ public class MergeRequestActivity extends BaseActivity {
Loading
@@ -50,108 +34,17 @@ public class MergeRequestActivity extends BaseActivity {
return intent; return intent;
} }
   
@Bind(R.id.toolbar) Toolbar mToolbar; @Bind(R.id.root)
@Bind(R.id.merge_request_title) TextView mMergeRequestTitle; ViewGroup mRoot;
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout; @Bind(R.id.toolbar)
@Bind(R.id.list) RecyclerView mNotesRecyclerView; Toolbar mToolbar;
@Bind(R.id.new_note_edit) EditText mNewNoteEdit; @Bind(R.id.tabs)
@Bind(R.id.progress) View mProgress; TabLayout mTabLayout;
@OnClick(R.id.new_note_button) @Bind(R.id.pager)
public void onNewNoteClick() { ViewPager mViewPager;
postNote();
}
private MergeRequestDetailAdapter mMergeRequestDetailAdapter;
private LinearLayoutManager mNotesLinearLayoutManager;
private Project mProject;
private MergeRequest mMergeRequest;
private Uri mNextPageUrl;
private boolean mLoading;
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mNotesLinearLayoutManager.getChildCount();
int totalItemCount = mNotesLinearLayoutManager.getItemCount();
int firstVisibleItem = mNotesLinearLayoutManager.findFirstVisibleItemPosition();
if (firstVisibleItem + visibleItemCount >= totalItemCount && !mLoading && mNextPageUrl != null) {
loadMoreNotes();
}
}
};
private Callback<List<Note>> mNotesCallback = new Callback<List<Note>>() {
@Override
public void onResponse(Response<List<Note>> response, Retrofit retrofit) {
mSwipeRefreshLayout.setRefreshing(false);
mLoading = false;
if (!response.isSuccess()) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
return;
}
mNextPageUrl = PaginationUtil.parse(response).getNext();
mMergeRequestDetailAdapter.setNotes(response.body());
}
@Override
public void onFailure(Throwable t) {
mLoading = false;
Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
private Callback<List<Note>> mMoreNotesCallback = new Callback<List<Note>>() {
@Override
public void onResponse(Response<List<Note>> response, Retrofit retrofit) {
mMergeRequestDetailAdapter.setLoading(false);
mLoading = false;
if (!response.isSuccess()) {
return;
}
mNextPageUrl = PaginationUtil.parse(response).getNext();
mMergeRequestDetailAdapter.addNotes(response.body());
}
@Override
public void onFailure(Throwable t) {
mLoading = false;
Timber.e(t, null);
mMergeRequestDetailAdapter.setLoading(false);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
   
private Callback<Note> mPostNoteCallback = new Callback<Note>() { Project mProject;
MergeRequest mMergeRequest;
@Override
public void onResponse(Response<Note> response, Retrofit retrofit) {
mProgress.setVisibility(View.GONE);
if (!response.isSuccess()) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
return;
}
mMergeRequestDetailAdapter.addNote(response.body());
mNotesRecyclerView.smoothScrollToPosition(mMergeRequestDetailAdapter.getItemCount());
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
   
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Loading
@@ -171,62 +64,17 @@ public class MergeRequestActivity extends BaseActivity {
Loading
@@ -171,62 +64,17 @@ public class MergeRequestActivity extends BaseActivity {
} }
}); });
mToolbar.setSubtitle(mProject.getNameWithNamespace()); mToolbar.setSubtitle(mProject.getNameWithNamespace());
mMergeRequestTitle.setText(mMergeRequest.getTitle()); setupTabs();
mMergeRequestDetailAdapter = new MergeRequestDetailAdapter(MergeRequestActivity.this, mMergeRequest);
mNotesLinearLayoutManager = new LinearLayoutManager(this);
mNotesRecyclerView.setLayoutManager(mNotesLinearLayoutManager);
mNotesRecyclerView.setAdapter(mMergeRequestDetailAdapter);
mNotesRecyclerView.addOnScrollListener(mOnScrollListener);
mNewNoteEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
postNote();
return true;
}
});
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadNotes();
}
});
loadNotes();
} }
   
private void loadNotes() { private void setupTabs() {
mSwipeRefreshLayout.post(new Runnable() { MergeRequestSectionsPagerAdapter sectionsPagerAdapter = new MergeRequestSectionsPagerAdapter(
@Override this,
public void run() { getSupportFragmentManager(),
if (mSwipeRefreshLayout != null) { mProject,
mSwipeRefreshLayout.setRefreshing(true); mMergeRequest);
}
}
});
GitLabClient.instance().getMergeRequestNotes(mProject.getId(), mMergeRequest.getId()).enqueue(mNotesCallback);
}
private void loadMoreNotes() {
mMergeRequestDetailAdapter.setLoading(true);
GitLabClient.instance().getMergeRequestNotes(mNextPageUrl.toString()).enqueue(mMoreNotesCallback);
}
private void postNote() {
String body = mNewNoteEdit.getText().toString();
if(body.length() < 1) {
return;
}
mProgress.setVisibility(View.VISIBLE);
mProgress.setAlpha(0.0f);
mProgress.animate().alpha(1.0f);
// Clear text & collapse keyboard
KeyboardUtil.hideKeyboard(this);
mNewNoteEdit.setText("");
   
GitLabClient.instance().addMergeRequestNote(mProject.getId(), mMergeRequest.getId(), body).enqueue(mPostNoteCallback); mViewPager.setAdapter(sectionsPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
} }
} }
Loading
@@ -5,16 +5,21 @@ import android.content.Context;
Loading
@@ -5,16 +5,21 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
   
import com.commit451.gitlab.LabCoatApp; import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.DividerItemDecoration;
import com.commit451.gitlab.adapter.MilestoneIssuesAdapter; import com.commit451.gitlab.adapter.MilestoneIssuesAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.MilestoneChangedEvent; import com.commit451.gitlab.event.MilestoneChangedEvent;
import com.commit451.gitlab.model.api.Issue; import com.commit451.gitlab.model.api.Issue;
Loading
@@ -31,9 +36,7 @@ import java.util.List;
Loading
@@ -31,9 +36,7 @@ import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import retrofit.Callback; import retrofit2.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber; import timber.log.Timber;
   
public class MilestoneActivity extends BaseActivity { public class MilestoneActivity extends BaseActivity {
Loading
@@ -60,11 +63,15 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -60,11 +63,15 @@ public class MilestoneActivity extends BaseActivity {
LinearLayoutManager mIssuesLayoutManager; LinearLayoutManager mIssuesLayoutManager;
@Bind(R.id.message_text) @Bind(R.id.message_text)
TextView mMessageText; TextView mMessageText;
@Bind(R.id.progress)
View mProgress;
   
private Project mProject; MenuItem mOpenCloseMenuItem;
private Milestone mMilestone;
private Uri mNextPageUrl; Project mProject;
private boolean mLoading = false; Milestone mMilestone;
Uri mNextPageUrl;
boolean mLoading = false;
   
EventReceiver mEventReceiver; EventReceiver mEventReceiver;
   
Loading
@@ -78,21 +85,13 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -78,21 +85,13 @@ public class MilestoneActivity extends BaseActivity {
NavigationManager.navigateToEditMilestone(MilestoneActivity.this, fab, mProject, mMilestone); NavigationManager.navigateToEditMilestone(MilestoneActivity.this, fab, mProject, mMilestone);
} }
   
private final Callback<List<Issue>> mIssuesCallback = new Callback<List<Issue>>() { private final Callback<List<Issue>> mIssuesCallback = new EasyCallback<List<Issue>>() {
@Override @Override
public void onResponse(Response<List<Issue>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Issue> response) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
mLoading = false; mLoading = false;
   
if (!response.isSuccess()) { if (!response.isEmpty()) {
Timber.e("Issues response was not a success: %d", response.code());
mMessageText.setVisibility(View.VISIBLE);
mMessageText.setText(R.string.connection_error_issues);
mMilestoneIssuesAdapter.setIssues(null);
return;
}
if (!response.body().isEmpty()) {
mMessageText.setVisibility(View.GONE); mMessageText.setVisibility(View.GONE);
} else { } else {
Timber.d("No issues found"); Timber.d("No issues found");
Loading
@@ -100,41 +99,54 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -100,41 +99,54 @@ public class MilestoneActivity extends BaseActivity {
mMessageText.setText(R.string.no_issues); mMessageText.setText(R.string.no_issues);
} }
   
mNextPageUrl = PaginationUtil.parse(response).getNext(); mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
mMilestoneIssuesAdapter.setIssues(response.body()); mMilestoneIssuesAdapter.setIssues(response);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mLoading = false; mLoading = false;
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
mMessageText.setVisibility(View.VISIBLE); mMessageText.setVisibility(View.VISIBLE);
mMessageText.setText(R.string.connection_error); mMessageText.setText(R.string.connection_error_issues);
mMilestoneIssuesAdapter.setIssues(null); mMilestoneIssuesAdapter.setIssues(null);
} }
}; };
   
private final Callback<List<Issue>> mMoreIssuesCallback = new Callback<List<Issue>>() { private final Callback<List<Issue>> mMoreIssuesCallback = new EasyCallback<List<Issue>>() {
@Override @Override
public void onResponse(Response<List<Issue>> response, Retrofit retrofit) { public void onResponse(@NonNull List<Issue> response) {
if (!response.isSuccess()) {
return;
}
mLoading = false; mLoading = false;
mNextPageUrl = PaginationUtil.parse(response).getNext(); mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
mMilestoneIssuesAdapter.addIssues(response.body()); mMilestoneIssuesAdapter.addIssues(response);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onAllFailure(Throwable t) {
Timber.e(t, null); Timber.e(t, null);
mLoading = false; mLoading = false;
} }
}; };
   
private final Callback<Milestone> mOpenCloseCallback = new EasyCallback<Milestone>() {
@Override
public void onResponse(@NonNull Milestone response) {
mProgress.setVisibility(View.GONE);
mMilestone = response;
LabCoatApp.bus().post(new MilestoneChangedEvent(mMilestone));
setOpenCloseMenuStatus();
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, getString(R.string.failed_to_create_milestone), Snackbar.LENGTH_SHORT)
.show();
}
};
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
Loading
@@ -166,6 +178,19 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -166,6 +178,19 @@ public class MilestoneActivity extends BaseActivity {
onBackPressed(); onBackPressed();
} }
}); });
mToolbar.inflateMenu(R.menu.menu_milestone);
mOpenCloseMenuItem = mToolbar.getMenu().findItem(R.id.action_close);
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_close:
closeOrOpenIssue();
return true;
}
return false;
}
});
   
mMilestoneIssuesAdapter = new MilestoneIssuesAdapter(new MilestoneIssuesAdapter.Listener() { mMilestoneIssuesAdapter = new MilestoneIssuesAdapter(new MilestoneIssuesAdapter.Listener() {
@Override @Override
Loading
@@ -177,6 +202,7 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -177,6 +202,7 @@ public class MilestoneActivity extends BaseActivity {
mIssuesRecyclerView.setAdapter(mMilestoneIssuesAdapter); mIssuesRecyclerView.setAdapter(mMilestoneIssuesAdapter);
mIssuesLayoutManager = new LinearLayoutManager(this); mIssuesLayoutManager = new LinearLayoutManager(this);
mIssuesRecyclerView.setLayoutManager(mIssuesLayoutManager); mIssuesRecyclerView.setLayoutManager(mIssuesLayoutManager);
mIssuesRecyclerView.addItemDecoration(new DividerItemDecoration(this));
mIssuesRecyclerView.addOnScrollListener(mOnScrollListener); mIssuesRecyclerView.addOnScrollListener(mOnScrollListener);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override @Override
Loading
@@ -197,6 +223,7 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -197,6 +223,7 @@ public class MilestoneActivity extends BaseActivity {
private void bind(Milestone milestone) { private void bind(Milestone milestone) {
mToolbar.setTitle(milestone.getTitle()); mToolbar.setTitle(milestone.getTitle());
mMilestoneIssuesAdapter.setMilestone(milestone); mMilestoneIssuesAdapter.setMilestone(milestone);
setOpenCloseMenuStatus();
} }
   
private void loadData() { private void loadData() {
Loading
@@ -221,10 +248,25 @@ public class MilestoneActivity extends BaseActivity {
Loading
@@ -221,10 +248,25 @@ public class MilestoneActivity extends BaseActivity {
   
mLoading = true; mLoading = true;
   
Timber.d("loadMore called for " + mNextPageUrl); Timber.d("loadMore called for %s", mNextPageUrl);
GitLabClient.instance().getMilestoneIssues(mNextPageUrl.toString()).enqueue(mMoreIssuesCallback); GitLabClient.instance().getMilestoneIssues(mNextPageUrl.toString()).enqueue(mMoreIssuesCallback);
} }
   
private void closeOrOpenIssue() {
mProgress.setVisibility(View.VISIBLE);
if (mMilestone.getState().equals(Milestone.STATE_ACTIVE)) {
GitLabClient.instance().updateMilestoneStatus(mProject.getId(), mMilestone.getId(), Milestone.STATE_EVENT_CLOSE)
.enqueue(mOpenCloseCallback);
} else {
GitLabClient.instance().updateMilestoneStatus(mProject.getId(), mMilestone.getId(), Milestone.STATE_EVENT_ACTIVATE)
.enqueue(mOpenCloseCallback);
}
}
private void setOpenCloseMenuStatus() {
mOpenCloseMenuItem.setTitle(mMilestone.getState().equals(Milestone.STATE_CLOSED) ? R.string.reopen : R.string.close);
}
private class EventReceiver { private class EventReceiver {
   
@Subscribe @Subscribe
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment