Skip to content
Snippets Groups Projects
Commit 38c2d95b authored by Michi302's avatar Michi302
Browse files

Merge branch 'master' into fdroid

# Conflicts:
#	.gitlab-ci.yml
#	.magnum.yml
#	app/build.gradle
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/com/commit451/gitlab/GitLabApp.java
parents 0216e5f3 d79d79f5
No related branches found
No related tags found
No related merge requests found
Pipeline #
Showing
with 1421 additions and 686 deletions
before_script: before_script:
- unset DISPLAY
- export TERM=dumb
- export _JAVA_OPTIONS="-Djava.awt.headless=true"
- apt-get -q -y update - apt-get -q -y update
- apt-get -q -y install wget tar openjdk-7-jdk lib32stdc++6 lib32z1 - apt-get -q -y install wget tar openjdk-7-jdk lib32stdc++6 lib32z1
- wget -q http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz - wget -q http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
- tar xvzf android-sdk_r24.4.1-linux.tgz - tar xzf android-sdk_r24.4.1-linux.tgz
- echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter tools,platform-tools,build-tools-23.0.2,android-23,extra-android-m2repository - echo y | android-sdk-linux/tools/android -s update sdk --no-ui --all --filter tools,platform-tools,build-tools-23.0.2,android-23,extra-android-m2repository
- export ANDROID_HOME=$PWD/android-sdk-linux - export ANDROID_HOME=$PWD/android-sdk-linux
- chmod +x prepare-build.sh - chmod +x gradlew
- ./prepare-build.sh
   
test: build:
script: script:
- ./gradlew build - ./gradlew build --stacktrace
before_script: before_script:
- wget http://dl.google.com/android/android-sdk_r24.4-macosx.zip - unset DISPLAY
- tar xvzf android-sdk_r24.4-macosx.zip - export TERM=dumb
- cd android-sdk-macosx/ - export _JAVA_OPTIONS="-Djava.awt.headless=true"
- ./tools/android update sdk --no-ui tools,platform-tools,build-tools-23.0.1,android-23,extra-android-m2repository - sudo apt-get -q -y update
- chmod +x scripts/prepare-build.sh - sudo apt-get -q -y install wget tar openjdk-7-jdk lib32stdc++6 lib32z1
- ./prepare-build.sh - wget -q http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
- tar xzf android-sdk_r24.4.1-linux.tgz
- echo y | android-sdk-linux/tools/android -s update sdk --no-ui --all --filter tools,platform-tools,build-tools-23.0.2,android-23,extra-android-m2repository
- export ANDROID_HOME=$PWD/android-sdk-linux
- chmod +x gradlew
   
script: script:
- ./gradlew build - ./gradlew build --stacktrace
language: android language: android
android: android:
components: components:
# Uncomment the lines below if you want to
# use the latest revision of Android SDK Tools
- platform-tools
- tools - tools
- platform-tools
# The BuildTools version used by your project - build-tools-23.0.2
- build-tools-23.0.1
# The SDK version used to compile your project
- android-23 - android-23
# Additional components
# - extra-google-google_play_services
# - extra-google-m2repository
- extra-android-m2repository - extra-android-m2repository
   
before_script: before_script:
- chmod +x scripts/prepare-build.sh - chmod +x gradlew
- ./prepare-build.sh
   
script: "./gradlew build" script: "./gradlew build --stacktrace"
Loading
@@ -11,22 +11,31 @@ Please see the [issues](https://gitlab.com/Commit451/GitLabAndroid/issues) secti
Loading
@@ -11,22 +11,31 @@ Please see the [issues](https://gitlab.com/Commit451/GitLabAndroid/issues) secti
report any bugs or feature requests and to see the list of known issues. report any bugs or feature requests and to see the list of known issues.
   
## Libraries ## Libraries
The following 3rd party libraries are the reason this app works. Rapid development is easily attainable thanks to these fine folks and the work they do: The following 3rd party libraries and resources are the reason this app works. Rapid development is easily attainable thanks to these fine folks and the work they do:
   
- AppCompat (https://developer.android.com/tools/support-library/features.html) - AppCompat (https://developer.android.com/tools/support-library/features.html)
- Design (https://developer.android.com/tools/support-library/features.html) - Design (https://developer.android.com/tools/support-library/features.html)
- RecyclerView (https://developer.android.com/tools/support-library/features.html) - RecyclerView (https://developer.android.com/tools/support-library/features.html)
- CardView (https://developer.android.com/tools/support-library/features.html)
- Palette (https://developer.android.com/tools/support-library/features.html)
- Picasso (http://square.github.io/picasso/)
- Retrofit (http://square.github.io/retrofit/) - Retrofit (http://square.github.io/retrofit/)
- OkHttp (http://square.github.io/okhttp/) - OkHttp (http://square.github.io/okhttp/)
- Picasso (http://square.github.io/picasso/) - Otto (http://square.github.io/otto/)
- Butter Knife (http://jakewharton.github.io/butterknife/) - Butter Knife (http://jakewharton.github.io/butterknife/)
- Timber (https://github.com/JakeWharton/timber) - Timber (https://github.com/JakeWharton/timber)
- GSON (https://github.com/google/gson) - GSON (https://github.com/google/gson)
- Joda Time Android (https://github.com/dlew/joda-time-android)
- Parceler (https://github.com/johncarl81/parceler) - Parceler (https://github.com/johncarl81/parceler)
- Bypass (https://github.com/Uncodin/bypass) - Bypasses (https://github.com/Commit451/bypasses)
- Easel (https://github.com/Commit451/Easel)
- CircleImageView (https://github.com/hdodenhof/CircleImageView)
- Material-ish Progress (https://github.com/pnikosis/materialish-progress) - Material-ish Progress (https://github.com/pnikosis/materialish-progress)
- PhysicsLayout (https://github.com/Jawnnypoo/PhysicsLayout) - PhysicsLayout (https://github.com/Jawnnypoo/PhysicsLayout)
- CircleImageView (https://github.com/hdodenhof/CircleImageView) - Material Letter Icon (https://github.com/IvBaranov/MaterialLetterIcon)
- RobotoTextView (https://github.com/johnkil/Android-RobotoTextView)
- GitDiffTextView (https://github.com/alorma/GitDiffTextView)
- MaterialDateTimePicker (https://github.com/wdullaer/MaterialDateTimePicker)
   
## 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
@@ -9,12 +9,12 @@ android {
Loading
@@ -9,12 +9,12 @@ android {
applicationId "com.commit451.gitlab" applicationId "com.commit451.gitlab"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 23 targetSdkVersion 23
versionCode 214 versionCode 220
versionName "2.1.4" versionName "2.2.0"
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug { debug {
Loading
@@ -34,8 +34,6 @@ dependencies {
Loading
@@ -34,8 +34,6 @@ dependencies {
compile 'com.android.support:recyclerview-v7:23.1.1' compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:cardview-v7:23.1.1' compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:palette-v7:23.1.1' compile 'com.android.support:palette-v7:23.1.1'
compile 'com.google.code.gson:gson:2.4'
compile 'net.danlew:android.joda:2.9.0'
compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
Loading
@@ -44,17 +42,21 @@ dependencies {
Loading
@@ -44,17 +42,21 @@ dependencies {
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.6.0' compile 'com.squareup.okhttp:okhttp:2.7.2'
compile 'com.squareup:otto:1.3.8' compile 'com.squareup:otto:1.3.8'
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.0'
compile 'de.hdodenhof:circleimageview:2.0.0' compile 'com.google.code.gson:gson:2.5'
compile 'com.pnikosis:materialish-progress:1.7' compile 'net.danlew:android.joda:2.9.1'
compile "org.parceler:parceler-api:1.0.3" compile "org.parceler:parceler-api:1.0.3"
apt "org.parceler:parceler:1.0.3" apt "org.parceler:parceler:1.0.3"
compile 'com.jawnnypoo:physicslayout:1.0.0'
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.4'
compile 'de.hdodenhof:circleimageview:2.0.0'
compile 'com.pnikosis:materialish-progress:1.7'
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.4.3'
compile 'com.github.alorma:diff-textview:1.1.0'
compile 'com.wdullaer:materialdatetimepicker:2.1.1'
} }
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:/Program Files/Android-Studio/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Just want proguard to strip unused things, don't care about people
# seeing the source
-dontobfuscate
# So that Fabric can still have line numbers
-keepattributes SourceFile,LineNumberTable
# Picasso rules
-dontwarn com.squareup.okhttp.**
# Retrofit rules
-keep class com.squareup.okhttp.** { *; }
-keep class retrofit.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
-dontwarn okio.**
-dontwarn retrofit.**
-dontwarn rx.**
-keepclasseswithmembers class * {
@retrofit.http.* <methods>;
}
# If in your rest service interface you use methods with Callback argument.
-keepattributes Exceptions
# If your rest service methods throw custom exceptions, because you've defined an ErrorHandler.
-keepattributes Signature
# Also you must note that if you are using GSON for conversion from JSON to POJO representation, you must ignore those POJO classes from being obfuscated.
# Here include the POJO's that have you have created for mapping JSON response to POJO for example.
## GSON 2.2.4 specific rules ##
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
-keepattributes EnclosingMethod
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.commit451.gitlab.model.** { *; }
# Simple-Xml Proguard Config
# Keep public classes and methods.
-dontwarn com.bea.xml.stream.**
-keep class org.simpleframework.xml.**{ *; }
-keepclassmembers,allowobfuscation class * {
@org.simpleframework.xml.* <fields>;
@org.simpleframework.xml.* <init>(...);
}
-dontwarn javax.xml.stream.events.**
-dontwarn javax.xml.**
# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
## Square Otto specific rules ##
## https://square.github.io/otto/ ##
-keepclassmembers class ** {
@com.squareup.otto.Subscribe public *;
@com.squareup.otto.Produce public *;
}
# ButterKnife 7
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
## joda-time-android 2.8.0
# This is only necessary if you are not including the optional joda-convert dependency
-dontwarn org.joda.convert.FromString
-dontwarn org.joda.convert.ToString
# Parcel library
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep class org.parceler.Parceler$$Parcels
# Unicoding Bypass library
-keep class in.uncod.android.** { *; }
\ No newline at end of file
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:/Program Files/Android-Studio/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
-dontwarn com.squareup.okhttp.**
-keep class retrofit.** { *; }
-dontwarn retrofit.**
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
\ No newline at end of file
Loading
@@ -10,12 +10,13 @@
Loading
@@ -10,12 +10,13 @@
<application <application
android:name="com.commit451.gitlab.GitLabApp" android:name="com.commit451.gitlab.GitLabApp"
android:allowBackup="true" android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme" > android:theme="@style/AppTheme" >
   
<activity <activity
android:name=".activities.GitlabActivity" android:name=".activity.GitlabActivity"
android:theme="@android:style/Theme.NoDisplay" android:theme="@android:style/Theme.NoDisplay"
android:noHistory="true" > android:noHistory="true" >
<intent-filter> <intent-filter>
Loading
@@ -24,38 +25,39 @@
Loading
@@ -24,38 +25,39 @@
</intent-filter> </intent-filter>
</activity> </activity>
   
<activity android:name=".activities.ProjectActivity" /> <activity android:name=".activity.ProjectActivity" />
   
<activity android:name=".activities.LoginActivity" /> <activity android:name=".activity.LoginActivity" />
   
<activity android:name=".activities.ProjectsActivity" <activity android:name=".activity.ProjectsActivity"
android:theme="@style/Activity.Projects"/> android:theme="@style/Activity.Projects"
android:launchMode="singleTask"/>
   
<activity android:name=".activities.GroupsActivity" <activity android:name=".activity.GroupsActivity"
android:theme="@style/Activity.Groups"/> android:theme="@style/Activity.Groups"
android:launchMode="singleTask"/>
   
<activity <activity
android:name=".activities.FileActivity" android:name=".activity.FileActivity">
android:configChanges="orientation|screenSize" >
</activity> </activity>
<activity <activity
android:name=".activities.IssueActivity" android:name=".activity.IssueActivity" >
android:configChanges="orientation|screenSize" >
</activity> </activity>
<activity <activity
android:name=".activities.DiffActivity" android:name=".activity.DiffActivity" >
android:configChanges="orientation|screenSize" >
</activity> </activity>
   
<activity android:name=".activities.AboutActivity"/> <activity android:name=".activity.AboutActivity"/>
<activity android:name=".activities.AddUserActivity"/> <activity android:name=".activity.AddUserActivity"/>
<activity android:name=".activities.UserActivity" <activity android:name=".activity.UserActivity"
android:theme="@style/Activity.User"/> android:theme="@style/Activity.User"/>
<activity android:name=".activities.SearchActivity"/> <activity android:name=".activity.SearchActivity"/>
<activity android:name=".activities.GroupActivity" <activity android:name=".activity.GroupActivity"
android:theme="@style/Activity.Group"/> android:theme="@style/Activity.Group"/>
<activity android:name=".activities.MergeRequestActivity"/> <activity android:name=".activity.MergeRequestActivity"/>
<activity android:name=".dialogs.NewIssuePopupDialog" android:theme="@style/Activity.Translucent"/> <activity android:name=".activity.AddIssueActivity"/>
<activity android:name=".activity.MilestoneActivity"/>
<activity android:name=".activity.AddMilestoneActivity"/>
</application> </application>
   
</manifest> </manifest>
\ No newline at end of file
package com.commit451.gitlab; package com.commit451.gitlab;
   
import android.app.Application; import android.app.Application;
import android.content.res.Configuration;
import android.content.res.Resources;
   
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
   
import net.danlew.android.joda.JodaTimeAndroid; import net.danlew.android.joda.JodaTimeAndroid;
   
import java.util.Locale;
import timber.log.Timber; import timber.log.Timber;
   
/** /**
* App for one time init things * App for one time init things and to house singletons
* Created by Jawn on 7/27/2015.
*/ */
public class GitLabApp extends Application { public class GitLabApp extends Application {
   
private static Bus bus; private static Bus sBus;
public static Bus bus() { public static Bus bus() {
if (bus == null) { if (sBus == null) {
bus = new Bus(); sBus = new Bus();
} }
return bus; return sBus;
} }
   
private static GitLabApp instance; private static GitLabApp sInstance;
public static GitLabApp instance() { public static GitLabApp instance() {
return instance; return sInstance;
} }
   
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
instance = this; sInstance = this;
forceLocale(Locale.ENGLISH);
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree()); Timber.plant(new Timber.DebugTree());
} }
JodaTimeAndroid.init(this); JodaTimeAndroid.init(this);
} }
private void forceLocale(Locale locale){
try {
Locale.setDefault(locale);
Resources[] resources = new Resources[]{
Resources.getSystem(),
getBaseContext().getResources()
};
for (Resources res : resources) {
Configuration configuration = res.getConfiguration();
configuration.locale = locale;
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
} catch (Exception e) {
Timber.e(e, null);
}
}
} }
package com.commit451.gitlab.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import com.commit451.gitlab.R;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.Diff;
import com.commit451.gitlab.model.DiffLine;
import com.commit451.gitlab.model.Project;
import com.commit451.gitlab.views.DiffView;
import com.commit451.gitlab.views.MessageView;
import org.parceler.Parcels;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
public class DiffActivity extends BaseActivity {
private static final String EXTRA_PROJECT = "extra_project";
private static final String EXTRA_COMMIT = "extra_commit";
public static Intent newInstance(Context context, Project project, DiffLine commit) {
Intent intent = new Intent(context, DiffActivity.class);
intent.putExtra(EXTRA_PROJECT, Parcels.wrap(project));
intent.putExtra(EXTRA_COMMIT, Parcels.wrap(commit));
return intent;
}
@Bind(R.id.toolbar) Toolbar toolbar;
@Bind(R.id.message_container) LinearLayout messageContainer;
@Bind(R.id.diff_container) LinearLayout diffContainer;
Project mProject;
DiffLine mCommit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_diff);
ButterKnife.bind(this);
mProject = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_PROJECT));
mCommit = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_COMMIT));
toolbar.setNavigationIcon(R.drawable.ic_back_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
toolbar.setTitle(mCommit.getShortId());
toolbar.inflateMenu(R.menu.diff);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.text_wrap_checkbox:
item.setChecked(!item.isChecked());
setTextWrap(item.isChecked());
return true;
}
return false;
}
});
//TODO make this use RecyclerViews, cause this is insane
GitLabClient.instance().getCommit(mProject.getId(), mCommit.getId()).enqueue(commitCallback);
GitLabClient.instance().getCommitDiff(mProject.getId(), mCommit.getId()).enqueue(diffCallback);
}
private Callback<DiffLine> commitCallback = new Callback<DiffLine>() {
@Override
public void onResponse(Response<DiffLine> response, Retrofit retrofit) {
if (response.isSuccess()) {
messageContainer.addView(new MessageView(DiffActivity.this, response.body()));
}
}
@Override
public void onFailure(Throwable t) {
Timber.e(t.toString());
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
private Callback<List<Diff>> diffCallback = new Callback<List<Diff>>() {
@Override
public void onResponse(Response<List<Diff>> response, Retrofit retrofit) {
if (response.isSuccess()) {
for(Diff diff : response.body()) {
diffContainer.addView(new DiffView(DiffActivity.this, diff));
}
}
}
@Override
public void onFailure(Throwable t) {
Timber.e(t.toString());
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
private void setTextWrap(boolean checked) {
((MessageView) messageContainer.getChildAt(0)).setWrapped(checked);
for(int i = 0; i < diffContainer.getChildCount(); ++i) {
((DiffView) diffContainer.getChildAt(i)).setWrapped(checked);
}
}
}
\ No newline at end of file
package com.commit451.gitlab.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.util.Base64;
import android.view.MenuItem;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.webkit.WebView;
import com.commit451.gitlab.R;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.FileResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
public class FileActivity extends BaseActivity {
private static final String EXTRA_PROJECT_ID = "extra_project_id";
private static final String EXTRA_PATH = "extra_path";
private static final String EXTRA_REF = "extra_ref";
public static Intent newIntent(Context context, long projectId, String path, String ref) {
Intent intent = new Intent(context, FileActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_PATH, path);
intent.putExtra(EXTRA_REF, ref);
return intent;
}
@Bind(R.id.toolbar) Toolbar toolbar;
@Bind(R.id.file_blob) WebView fileBlobView;
@Bind(R.id.progress) View progress;
long mProjectId;
String mPath;
String mRef;
String mFileName;
byte[] mBlob;
private final Callback<FileResponse> mFileResponseCallback = new Callback<FileResponse>() {
@Override
public void onResponse(Response<FileResponse> response, Retrofit retrofit) {
if (!response.isSuccess()) {
return;
}
progress.setVisibility(View.GONE);
String text = getString(R.string.file_load_error);
// Receiving side
mFileName = response.body().getFileName();
mBlob = Base64.decode(response.body().getContent(), Base64.DEFAULT);
String content;
String mimeType = null;
String ext = fileExt(mFileName);
if (ext != null) {
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext.substring(1));
}
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 {
try {
text = new String(mBlob, "UTF-8");
}
catch (UnsupportedEncodingException e) {
Timber.e(e.toString());
}
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>";
}
fileBlobView.loadDataWithBaseURL("file:///android_asset/", content, "text/html", "utf8", null);
toolbar.setTitle(mFileName);
toolbar.inflateMenu(R.menu.file);
}
@Override
public void onFailure(Throwable t) {
progress.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), R.string.file_load_error, Snackbar.LENGTH_SHORT)
.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
ButterKnife.bind(this);
mProjectId = getIntent().getLongExtra(EXTRA_PROJECT_ID, -1);
mPath = getIntent().getStringExtra(EXTRA_PATH);
mRef = getIntent().getStringExtra(EXTRA_REF);
setupUI();
load();
}
private void load() {
progress.setVisibility(View.VISIBLE);
GitLabClient.instance().getFile(mProjectId, mPath, mRef).enqueue(mFileResponseCallback);
}
private void setupUI() {
toolbar.setNavigationIcon(R.drawable.ic_back_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_open:
openFile();
return true;
case R.id.action_save:
saveBlob();
return true;
}
return false;
}
});
}
private File saveBlob() {
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state) && mBlob != null) {
File downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File newFile = new File(downloadFolder, mFileName);
try {
FileOutputStream f = new FileOutputStream(newFile);
f.write(mBlob);
f.close();
Snackbar.make(getWindow().getDecorView(), getString(R.string.file_saved), Snackbar.LENGTH_SHORT)
.show();
return newFile;
}
catch(IOException e) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show();
}
}
else {
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show();
}
return null;
}
private void openFile() {
File file = saveBlob();
if(file == null) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show();
return;
}
MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String fileExt = fileExt(file.toString());
if (fileExt == null) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show();
return;
}
String mimeType = myMime.getMimeTypeFromExtension(fileExt.substring(1));
newIntent.setDataAndType(Uri.fromFile(file), mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(newIntent);
}
catch(android.content.ActivityNotFoundException e) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show();
}
}
private String fileExt(String url) {
if(url.contains("?")) {
url = url.substring(0, url.indexOf("?"));
}
if(!url.contains(".")) {
return null;
}
else {
String ext = url.substring(url.lastIndexOf("."));
if(ext.contains("%")) {
ext = ext.substring(0, ext.indexOf("%"));
}
if(ext.contains("/")) {
ext = ext.substring(0, ext.indexOf("/"));
}
return ext.toLowerCase();
}
}
}
package com.commit451.gitlab.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.commit451.gitlab.GitLabApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.SectionsPagerAdapter;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.events.ProjectReloadEvent;
import com.commit451.gitlab.fragments.CommitsFragment;
import com.commit451.gitlab.fragments.FilesFragment;
import com.commit451.gitlab.fragments.IssuesFragment;
import com.commit451.gitlab.fragments.MergeRequestsFragment;
import com.commit451.gitlab.fragments.MembersFragment;
import com.commit451.gitlab.fragments.OverviewFragment;
import com.commit451.gitlab.model.Branch;
import com.commit451.gitlab.model.Project;
import com.commit451.gitlab.tools.IntentUtil;
import org.parceler.Parcels;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
public class ProjectActivity extends BaseActivity {
private static final String EXTRA_PROJECT = "extra_project";
public static Intent newInstance(Context context, Project project) {
Intent intent = new Intent(context, ProjectActivity.class);
intent.putExtra(EXTRA_PROJECT, Parcels.wrap(project));
return intent;
}
@Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.tabs) TabLayout mTabLayout;
@Bind(R.id.branch_spinner) Spinner mBranchSpinner;
@Bind(R.id.progress) View mProgress;
@Bind(R.id.pager) ViewPager mViewPager;
private final AdapterView.OnItemSelectedListener mSpinnerItemSelectedListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mBranchName = ((TextView)view).getText().toString();
broadcastLoad();
}
@Override
public void onNothingSelected(AdapterView<?> parent) { }
};
Project mProject;
String mBranchName;
private Callback<List<Branch>> mBranchesCallback = new Callback<List<Branch>>() {
@Override
public void onResponse(Response<List<Branch>> response, Retrofit retrofit) {
if (!response.isSuccess()) {
return;
}
mProgress.setVisibility(View.GONE);
if(response.body().isEmpty()) {
mBranchSpinner.setVisibility(View.GONE);
} else {
mBranchSpinner.setVisibility(View.VISIBLE);
mBranchSpinner.setAlpha(0.0f);
mBranchSpinner.animate().alpha(1.0f);
// Set up the dropdown list navigation in the action bar.
mBranchSpinner.setAdapter(new ArrayAdapter<>(ProjectActivity.this, android.R.layout.simple_list_item_1, android.R.id.text1, response.body()));
}
for (int i=0; i<response.body().size(); i++) {
if (response.body().get(i).getName().equals(mProject.getDefaultBranch())) {
mBranchSpinner.setSelection(i);
}
}
mBranchSpinner.setOnItemSelectedListener(mSpinnerItemSelectedListener);
if(response.body().isEmpty()) {
broadcastLoad();
}
}
@Override
public void onFailure(Throwable t) {
mProgress.setVisibility(View.GONE);
Timber.e(t.toString());
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
private final Toolbar.OnMenuItemClickListener mOnMenuItemClickListener = new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_share:
IntentUtil.share(getWindow().getDecorView(), mProject.getWebUrl());
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project);
ButterKnife.bind(this);
mProject = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_PROJECT));
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mToolbar.inflateMenu(R.menu.menu_repository);
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
mViewPager.setAdapter(sectionsPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
loadBranches();
}
private void loadBranches() {
GitLabClient.instance().getBranches(mProject.getId()).enqueue(mBranchesCallback);
}
private void broadcastLoad() {
GitLabApp.bus().post(new ProjectReloadEvent(mProject, mBranchName));
}
@Override
public void onBackPressed() {
boolean handled = false;
switch(mViewPager.getCurrentItem()) {
case 0:
OverviewFragment overviewFragment = (OverviewFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":0");
handled = overviewFragment.onBackPressed();
break;
case 1:
CommitsFragment commitsFragment = (CommitsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":1");
handled = commitsFragment.onBackPressed();
break;
case 2:
IssuesFragment issuesFragment = (IssuesFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":2");
handled = issuesFragment.onBackPressed();
break;
case 3:
FilesFragment filesFragment = (FilesFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":3");
handled = filesFragment.onBackPressed();
break;
case 4:
MergeRequestsFragment mergeRequestsFragment = (MergeRequestsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":4");
handled = mergeRequestsFragment.onBackPressed();
break;
case 5:
MembersFragment membersFragment = (MembersFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":5");
handled = membersFragment.onBackPressed();
break;
}
if(!handled) {
super.onBackPressed();
}
}
public String getBranchName() {
return mBranchName;
}
public Project getProject() {
return mProject;
}
}
package com.commit451.gitlab.activities; package com.commit451.gitlab.activity;
   
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
Loading
@@ -7,6 +7,7 @@ import android.hardware.Sensor;
Loading
@@ -7,6 +7,7 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
Loading
@@ -16,14 +17,13 @@ import android.widget.TextView;
Loading
@@ -16,14 +17,13 @@ import android.widget.TextView;
   
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.Contributor; import com.commit451.gitlab.model.api.Contributor;
import com.commit451.gitlab.tools.ImageUtil; import com.commit451.gitlab.util.ImageUtil;
import com.commit451.gitlab.tools.IntentUtil; import com.commit451.gitlab.util.IntentUtil;
import com.commit451.gitlab.tools.WindowUtil; import com.commit451.gitlab.util.WindowUtil;
import com.jawnnypoo.physicslayout.Physics; import com.jawnnypoo.physicslayout.Physics;
import com.jawnnypoo.physicslayout.PhysicsConfig; import com.jawnnypoo.physicslayout.PhysicsConfig;
import com.jawnnypoo.physicslayout.PhysicsFrameLayout; import com.jawnnypoo.physicslayout.PhysicsFrameLayout;
import com.squareup.picasso.Picasso;
   
import org.jbox2d.common.Vec2; import org.jbox2d.common.Vec2;
   
Loading
@@ -57,7 +57,7 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -57,7 +57,7 @@ public class AboutActivity extends BaseActivity {
@Bind(R.id.physics_layout) PhysicsFrameLayout physicsLayout; @Bind(R.id.physics_layout) PhysicsFrameLayout physicsLayout;
@OnClick(R.id.sauce) @OnClick(R.id.sauce)
void onSauceClick() { void onSauceClick() {
IntentUtil.openPage(root, getString(R.string.source_url)); IntentUtil.openPage(root, Uri.parse(getString(R.string.source_url)));
} }
   
SensorManager sensorManager; SensorManager sensorManager;
Loading
@@ -84,14 +84,14 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -84,14 +84,14 @@ public class AboutActivity extends BaseActivity {
if (!response.isSuccess()) { if (!response.isSuccess()) {
return; return;
} }
addContributors(response.body()); addContributors(Contributor.groupContributors(response.body()));
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
Timber.e(t, null);
Snackbar.make(getWindow().getDecorView(), R.string.failed_to_load_contributors, Snackbar.LENGTH_SHORT) Snackbar.make(getWindow().getDecorView(), R.string.failed_to_load_contributors, Snackbar.LENGTH_SHORT)
.show(); .show();
Timber.e(t.toString());
} }
}; };
   
Loading
@@ -157,8 +157,9 @@ public class AboutActivity extends BaseActivity {
Loading
@@ -157,8 +157,9 @@ public class AboutActivity extends BaseActivity {
x = 0; x = 0;
y = (y + imageSize) % physicsLayout.getHeight(); y = (y + imageSize) % physicsLayout.getHeight();
} }
String url = ImageUtil.getGravatarUrl(contributor.getEmail(), imageSize);
Picasso.with(this) Uri url = ImageUtil.getAvatarUrl(contributor.getEmail(), imageSize);
GitLabClient.getPicasso()
.load(url) .load(url)
.into(imageView); .into(imageView);
} }
Loading
Loading
package com.commit451.gitlab.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.commit451.gitlab.GitLabApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.AssigneeSpinnerAdapter;
import com.commit451.gitlab.adapter.MilestoneSpinnerAdapter;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.IssueChangedEvent;
import com.commit451.gitlab.event.IssueCreatedEvent;
import com.commit451.gitlab.model.api.Issue;
import com.commit451.gitlab.model.api.Member;
import com.commit451.gitlab.model.api.Milestone;
import com.commit451.gitlab.model.api.Project;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
/**
* Activity to input new issues, but not really a dialog at all wink wink
*/
public class AddIssueActivity extends MorphActivity {
private static final String KEY_PROJECT = "project";
private static final String KEY_ISSUE = "issue";
public static Intent newIntent(Context context, Project project, Issue issue) {
Intent intent = new Intent(context, AddIssueActivity.class);
intent.putExtra(KEY_PROJECT, Parcels.wrap(project));
if (issue != null) {
intent.putExtra(KEY_ISSUE, Parcels.wrap(issue));
}
return intent;
}
@Bind(R.id.root) ViewGroup mRoot;
@Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.title_text_input_layout) TextInputLayout mTitleInputLayout;
@Bind(R.id.title) EditText mTitleInput;
@Bind(R.id.description) 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 Issue mIssue;
private HashSet<Member> mMembers;
private final Callback<List<Milestone>> mMilestonesCallback = new Callback<List<Milestone>>() {
@Override
public void onResponse(Response<List<Milestone>> response, Retrofit retrofit) {
mMilestoneProgress.setVisibility(View.GONE);
if (!response.isSuccess()) {
mMilestoneSpinner.setVisibility(View.GONE);
return;
}
mMilestoneSpinner.setVisibility(View.VISIBLE);
MilestoneSpinnerAdapter milestoneSpinnerAdapter = new MilestoneSpinnerAdapter(AddIssueActivity.this, response.body());
mMilestoneSpinner.setAdapter(milestoneSpinnerAdapter);
if (mIssue != null) {
mMilestoneSpinner.setSelection(milestoneSpinnerAdapter.getSelectedItemPosition(mIssue.getMilestone()));
}
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mMilestoneProgress.setVisibility(View.GONE);
mMilestoneSpinner.setVisibility(View.GONE);
}
};
private final Callback<List<Member>> mAssigneeCallback = new Callback<List<Member>>() {
@Override
public void onResponse(Response<List<Member>> response, Retrofit retrofit) {
if (!response.isSuccess()) {
mAssigneeProgress.setVisibility(View.GONE);
mAssigneeSpinner.setVisibility(View.GONE);
return;
}
if (response.body() != null) {
mMembers.addAll(response.body());
}
if (mProject.belongsToGroup()) {
Timber.d("Project belongs to a group, loading those users too");
GitLabClient.instance().getGroupMembers(mProject.getNamespace().getId()).enqueue(mGroupMembersCallback);
} else {
setAssignees();
}
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mAssigneeSpinner.setVisibility(View.GONE);
mAssigneeProgress.setVisibility(View.GONE);
}
};
private final Callback<List<Member>> mGroupMembersCallback = new Callback<List<Member>>() {
@Override
public void onResponse(Response<List<Member>> response, Retrofit retrofit) {
if (!response.isSuccess()) {
mAssigneeSpinner.setVisibility(View.GONE);
return;
}
if (response.body() != null) {
mMembers.addAll(response.body());
}
setAssignees();
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mAssigneeSpinner.setVisibility(View.GONE);
mAssigneeProgress.setVisibility(View.GONE);
}
};
private final Callback<Issue> mIssueCreatedCallback = new Callback<Issue>() {
@Override
public void onResponse(Response<Issue> response, Retrofit retrofit) {
if (!response.isSuccess()) {
Toast.makeText(AddIssueActivity.this, getString(R.string.failed_to_create_issue), Toast.LENGTH_SHORT)
.show();
return;
}
if (mIssue == null) {
GitLabApp.bus().post(new IssueCreatedEvent(response.body()));
} else {
GitLabApp.bus().post(new IssueChangedEvent(response.body()));
}
dismiss();
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
Toast.makeText(AddIssueActivity.this, getString(R.string.connection_error), Toast.LENGTH_SHORT)
.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_issue);
ButterKnife.bind(this);
morph(mRoot);
mProject = Parcels.unwrap(getIntent().getParcelableExtra(KEY_PROJECT));
mIssue = Parcels.unwrap(getIntent().getParcelableExtra(KEY_ISSUE));
mMembers = new HashSet<>();
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create:
case R.id.action_edit:
save();
return true;
}
return false;
}
});
if (mIssue != null) {
bindIssue();
mToolbar.inflateMenu(R.menu.menu_edit_milestone);
} else {
mToolbar.inflateMenu(R.menu.menu_add_milestone);
}
load();
}
private void load() {
GitLabClient.instance().getMilestones(mProject.getId()).enqueue(mMilestonesCallback);
GitLabClient.instance().getProjectMembers(mProject.getId()).enqueue(mAssigneeCallback);
}
private void showLoading() {
mProgress.setVisibility(View.VISIBLE);
mProgress.setAlpha(0.0f);
mProgress.animate().alpha(1.0f);
}
private void bindIssue() {
if (!TextUtils.isEmpty(mIssue.getTitle())) {
mTitleInput.setText(mIssue.getTitle());
}
if (!TextUtils.isEmpty(mIssue.getDescription())) {
mDescriptionInput.setText(mIssue.getDescription());
}
}
private void setAssignees() {
mAssigneeProgress.setVisibility(View.GONE);
mAssigneeSpinner.setVisibility(View.VISIBLE);
AssigneeSpinnerAdapter assigneeSpinnerAdapter = new AssigneeSpinnerAdapter(this, new ArrayList<>(mMembers));
mAssigneeSpinner.setAdapter(assigneeSpinnerAdapter);
if (mIssue != null) {
mAssigneeSpinner.setSelection(assigneeSpinnerAdapter.getSelectedItemPosition(mIssue.getAssignee()));
}
}
private void save() {
if(!TextUtils.isEmpty(mTitleInput.getText())) {
mTitleInputLayout.setError(null);
showLoading();
Long assigneeId = null;
if (mAssigneeSpinner.getAdapter() != null ) {
//the user did make a selection of some sort. So update it
Member member = (Member) mAssigneeSpinner.getSelectedItem();
if (member == null) {
//Removes the assignment
assigneeId = 0L;
} else {
assigneeId = member.getId();
}
}
Long milestoneId = null;
if (mMilestoneSpinner.getAdapter() != null) {
//the user did make a selection of some sort. So update it
Milestone milestone = (Milestone) mMilestoneSpinner.getSelectedItem();
if (milestone == null) {
//Removes the assignment
milestoneId = 0L;
} else {
milestoneId = milestone.getId();
}
}
createOrSaveIssue(mTitleInput.getText().toString(),
mDescriptionInput.getText().toString(),
assigneeId,
milestoneId);
}
else {
mTitleInputLayout.setError(getString(R.string.required_field));
}
}
private void createOrSaveIssue(String title, String description, Long assigneeId, Long milestoneId) {
if (mIssue == null) {
GitLabClient.instance().createIssue(
mProject.getId(),
title,
description,
assigneeId,
milestoneId).enqueue(mIssueCreatedCallback);
} else {
GitLabClient.instance().updateIssue(mProject.getId(),
mIssue.getId(),
title,
description,
assigneeId,
milestoneId).enqueue(mIssueCreatedCallback);
}
}
}
\ No newline at end of file
package com.commit451.gitlab.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.commit451.gitlab.GitLabApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.MilestoneChangedEvent;
import com.commit451.gitlab.event.MilestoneCreatedEvent;
import com.commit451.gitlab.model.api.Milestone;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import org.parceler.Parcels;
import java.util.Calendar;
import java.util.Date;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
public class AddMilestoneActivity extends MorphActivity {
private static final String KEY_PROJECT_ID = "project_id";
private static final String KEY_MILESTONE = "milestone";
public static Intent newInstance(Context context, long projectId) {
return newInstance(context, projectId, null);
}
public static Intent newInstance(Context context, long projectId, Milestone milestone) {
Intent intent = new Intent(context, AddMilestoneActivity.class);
intent.putExtra(KEY_PROJECT_ID, projectId);
if (milestone != null) {
intent.putExtra(KEY_MILESTONE, Parcels.wrap(milestone));
}
return intent;
}
@Bind(R.id.root)
View mRoot;
@Bind(R.id.toolbar)
Toolbar mToolbar;
@Bind(R.id.title_text_input_layout)
TextInputLayout mTitleTextInputLayout;
@Bind(R.id.title)
EditText mTitle;
@Bind(R.id.description)
EditText mDescription;
@Bind(R.id.due_date)
Button mDueDate;
@Bind(R.id.progress)
View mProgress;
@OnClick(R.id.due_date)
void onDueDateClicked() {
Calendar now = Calendar.getInstance();
if (mCurrentDate != null) {
now.setTime(mCurrentDate);
}
DatePickerDialog dpd = DatePickerDialog.newInstance(
mOnDateSetListener,
now.get(Calendar.YEAR),
now.get(Calendar.MONTH),
now.get(Calendar.DAY_OF_MONTH)
);
dpd.show(getFragmentManager(), "date_picker");
}
long mProjectId;
Milestone mMilestone;
Date mCurrentDate;
private final DatePickerDialog.OnDateSetListener mOnDateSetListener = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, monthOfYear);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
mCurrentDate = calendar.getTime();
bind(mCurrentDate);
}
};
private final View.OnClickListener mOnBackPressed = new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
};
private Callback<Milestone> mMilestoneCallback = new Callback<Milestone>() {
@Override
public void onResponse(Response<Milestone> response, Retrofit retrofit) {
mProgress.setVisibility(View.GONE);
if (!response.isSuccess()) {
showError();
return;
}
if (mMilestone == null) {
GitLabApp.bus().post(new MilestoneCreatedEvent(response.body()));
} else {
GitLabApp.bus().post(new MilestoneChangedEvent(response.body()));
}
finish();
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
showError();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_milestone);
ButterKnife.bind(this);
morph(mRoot);
mProjectId = getIntent().getLongExtra(KEY_PROJECT_ID, -1);
mMilestone = Parcels.unwrap(getIntent().getParcelableExtra(KEY_MILESTONE));
if (mMilestone != null) {
bind(mMilestone);
mToolbar.inflateMenu(R.menu.menu_edit_milestone);
} else {
mToolbar.inflateMenu(R.menu.menu_add_milestone);
}
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(mOnBackPressed);
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create:
case R.id.action_edit:
createMilestone();
return true;
}
return false;
}
});
}
private void createMilestone() {
if (TextUtils.isEmpty(mTitle.getText())) {
mTitleTextInputLayout.setError(getString(R.string.required_field));
return;
}
mProgress.setVisibility(View.VISIBLE);
String dueDate = null;
if (mCurrentDate != null) {
dueDate = Milestone.DUE_DATE_FORMAT.format(mCurrentDate);
}
if (mMilestone == null) {
GitLabClient.instance().createMilestone(mProjectId,
mTitle.getText().toString(),
mDescription.getText().toString(),
dueDate).enqueue(mMilestoneCallback);
} else {
GitLabClient.instance().editMilestone(mProjectId,
mMilestone.getId(),
mTitle.getText().toString(),
mDescription.getText().toString(),
dueDate).enqueue(mMilestoneCallback);
}
}
private void showError() {
Snackbar.make(mRoot, getString(R.string.failed_to_create_milestone), Snackbar.LENGTH_SHORT)
.show();
}
private void bind(Date date) {
mDueDate.setText(Milestone.DUE_DATE_FORMAT.format(date));
}
private void bind(Milestone milestone) {
mTitle.setText(milestone.getTitle());
if (milestone.getDescription() != null) {
mDescription.setText(milestone.getDescription());
}
if (milestone.getDueDate() != null) {
mCurrentDate = milestone.getDueDate();
bind(mCurrentDate);
}
}
}
package com.commit451.gitlab.activities; 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.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
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.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
Loading
@@ -17,14 +21,16 @@ import android.widget.Toast;
Loading
@@ -17,14 +21,16 @@ import android.widget.Toast;
   
import com.commit451.gitlab.GitLabApp; import com.commit451.gitlab.GitLabApp;
import com.commit451.gitlab.R; import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.MemberAdapter; import com.commit451.gitlab.adapter.UsersAdapter;
import com.commit451.gitlab.api.GitLabClient; import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.dialogs.UserRoleDialog; import com.commit451.gitlab.dialog.AccessDialog;
import com.commit451.gitlab.events.UserAddedEvent; import com.commit451.gitlab.event.MemberAddedEvent;
import com.commit451.gitlab.model.Group; import com.commit451.gitlab.model.api.Group;
import com.commit451.gitlab.model.User; import com.commit451.gitlab.model.api.Member;
import com.commit451.gitlab.tools.KeyboardUtil; import com.commit451.gitlab.model.api.UserBasic;
import com.commit451.gitlab.viewHolders.MemberViewHolder; import com.commit451.gitlab.util.KeyboardUtil;
import com.commit451.gitlab.util.PaginationUtil;
import com.commit451.gitlab.viewHolder.UserViewHolder;
   
import org.parceler.Parcels; import org.parceler.Parcels;
   
Loading
@@ -32,6 +38,7 @@ import java.util.List;
Loading
@@ -32,6 +38,7 @@ import java.util.List;
   
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick;
import retrofit.Callback; import retrofit.Callback;
import retrofit.Response; import retrofit.Response;
import retrofit.Retrofit; import retrofit.Retrofit;
Loading
@@ -39,9 +46,8 @@ import timber.log.Timber;
Loading
@@ -39,9 +46,8 @@ import timber.log.Timber;
   
/** /**
* Add a new user to the repo or to the group, depending on the mode * Add a new user to the repo or to the group, depending on the mode
* Created by Jawn on 9/15/2015.
*/ */
public class AddUserActivity extends BaseActivity { public class AddUserActivity extends MorphActivity {
   
private static final String KEY_PROJECT_ID = "project_id"; private static final String KEY_PROJECT_ID = "project_id";
private static final String KEY_GROUP = "group"; private static final String KEY_GROUP = "group";
Loading
@@ -58,15 +64,33 @@ public class AddUserActivity extends BaseActivity {
Loading
@@ -58,15 +64,33 @@ public class AddUserActivity extends BaseActivity {
return intent; return intent;
} }
   
@Bind(R.id.root) View mRoot;
@Bind(R.id.toolbar) Toolbar mToolbar; @Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.userSearch) EditText mUserSearch; @Bind(R.id.search) EditText mUserSearch;
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout; @Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list) RecyclerView mRecyclerView; @Bind(R.id.list) RecyclerView mRecyclerView;
MemberAdapter mAdapter; @Bind(R.id.clear) View mClearView;
UserRoleDialog mUserRoleDialog; LinearLayoutManager mUserLinearLayoutManager;
User mSelectedUser;
@OnClick(R.id.clear)
void onClearClick() {
mClearView.animate().alpha(0.0f).withEndAction(new Runnable() {
@Override
public void run() {
mClearView.setVisibility(View.GONE);
mUserSearch.getText().clear();
}
});
}
UsersAdapter mAdapter;
AccessDialog mAccessDialog;
UserBasic mSelectedUser;
long mProjectId; long mProjectId;
Group mGroup; Group mGroup;
String mSearchQuery;
Uri mNextPageUrl;
boolean mLoading = false;
   
private final View.OnClickListener mOnBackPressed = new View.OnClickListener() { private final View.OnClickListener mOnBackPressed = new View.OnClickListener() {
@Override @Override
Loading
@@ -75,49 +99,109 @@ public class AddUserActivity extends BaseActivity {
Loading
@@ -75,49 +99,109 @@ public class AddUserActivity extends BaseActivity {
} }
}; };
   
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 = mUserLinearLayoutManager.getChildCount();
int totalItemCount = mUserLinearLayoutManager.getItemCount();
int firstVisibleItem = mUserLinearLayoutManager.findFirstVisibleItemPosition();
if (firstVisibleItem + visibleItemCount >= totalItemCount && !mLoading && mNextPageUrl != null) {
loadMore();
}
}
};
private final TextView.OnEditorActionListener mSearchEditorActionListener = new TextView.OnEditorActionListener() { private final TextView.OnEditorActionListener mSearchEditorActionListener = new TextView.OnEditorActionListener() {
@Override @Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (!TextUtils.isEmpty(mUserSearch.getText())) { if (!TextUtils.isEmpty(mUserSearch.getText())) {
KeyboardUtil.hideKeyboard(AddUserActivity.this); mSearchQuery = mUserSearch.getText().toString();
mSwipeRefreshLayout.setRefreshing(true); loadData();
GitLabClient.instance().searchUsers(mUserSearch.getText().toString()).enqueue(mUserCallback);
} }
return true; return true;
} }
}; };
   
private final Callback<List<User>> mUserCallback = new Callback<List<User>>() { private final TextWatcher mTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (TextUtils.isEmpty(s)) {
mClearView.animate().alpha(0.0f).withEndAction(new Runnable() {
@Override
public void run() {
mClearView.setVisibility(View.GONE);
}
});
} else {
mClearView.setVisibility(View.VISIBLE);
mClearView.animate().alpha(1.0f);
}
}
@Override
public void afterTextChanged(Editable s) {}
};
private final Callback<List<UserBasic>> mUserCallback = new Callback<List<UserBasic>>() {
@Override @Override
public void onResponse(Response<List<User>> response, Retrofit retrofit) { public void onResponse(Response<List<UserBasic>> response, Retrofit retrofit) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
mLoading = false;
if (!response.isSuccess()) { if (!response.isSuccess()) {
return; return;
} }
mAdapter.setData(response.body()); mAdapter.setData(response.body());
mNextPageUrl = PaginationUtil.parse(response).getNext();
Timber.d("HAHA Next page url is " + mNextPageUrl);
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
Timber.e(t.toString()); Timber.e(t, null);
mLoading = false;
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error_users), Snackbar.LENGTH_SHORT) Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error_users), Snackbar.LENGTH_SHORT)
.show(); .show();
} }
}; };
   
private final MemberAdapter.Listener mUserClickListener = new MemberAdapter.Listener() { private final Callback<List<UserBasic>> mMoreUsersCallback = new Callback<List<UserBasic>>() {
@Override @Override
public void onUserClicked(User user, MemberViewHolder memberViewHolder) { public void onResponse(Response<List<UserBasic>> response, Retrofit retrofit) {
mLoading = false;
if (!response.isSuccess()) {
return;
}
mAdapter.addData(response.body());
mNextPageUrl = PaginationUtil.parse(response).getNext();
}
@Override
public void onFailure(Throwable t) {
Timber.e(t, null);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error_users), Snackbar.LENGTH_SHORT)
.show();
}
};
private final UsersAdapter.Listener mUserClickListener = new UsersAdapter.Listener() {
@Override
public void onUserClicked(UserBasic user, UserViewHolder userViewHolder) {
mSelectedUser = user; mSelectedUser = user;
mUserRoleDialog.show(); mAccessDialog.show();
} }
}; };
   
private final UserRoleDialog.Listener mUserRoleDialogListener = new UserRoleDialog.Listener() { private final AccessDialog.OnAccessAppliedListener mOnAccessAppliedListener = new AccessDialog.OnAccessAppliedListener() {
@Override @Override
public void onAccessLevelClicked(String accessLevel) { public void onAccessApplied(int accessLevel) {
mAccessDialog.showLoading();
if (mGroup == null) { if (mGroup == null) {
GitLabClient.instance().addProjectTeamMember( GitLabClient.instance().addProjectMember(
mProjectId, mProjectId,
mSelectedUser.getId(), mSelectedUser.getId(),
accessLevel).enqueue(mAddGroupMemeberCallback); accessLevel).enqueue(mAddGroupMemeberCallback);
Loading
@@ -129,9 +213,9 @@ public class AddUserActivity extends BaseActivity {
Loading
@@ -129,9 +213,9 @@ public class AddUserActivity extends BaseActivity {
} }
}; };
   
private final Callback<User> mAddGroupMemeberCallback = new Callback<User>() { private final Callback<Member> mAddGroupMemeberCallback = new Callback<Member>() {
@Override @Override
public void onResponse(Response<User> response, Retrofit retrofit) { public void onResponse(Response<Member> response, Retrofit retrofit) {
if (!response.isSuccess()) { if (!response.isSuccess()) {
//Conflict //Conflict
if (response.code() == 409) { if (response.code() == 409) {
Loading
@@ -140,14 +224,14 @@ public class AddUserActivity extends BaseActivity {
Loading
@@ -140,14 +224,14 @@ public class AddUserActivity extends BaseActivity {
return; return;
} }
Toast.makeText(AddUserActivity.this, R.string.user_added_successfully, Toast.LENGTH_SHORT).show(); Toast.makeText(AddUserActivity.this, R.string.user_added_successfully, Toast.LENGTH_SHORT).show();
mUserRoleDialog.dismiss(); mAccessDialog.dismiss();
finish(); dismiss();
GitLabApp.bus().post(new UserAddedEvent(response.body())); GitLabApp.bus().post(new MemberAddedEvent(response.body()));
} }
   
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
Timber.e(t.toString()); Timber.e(t, null);
} }
}; };
   
Loading
@@ -158,12 +242,30 @@ public class AddUserActivity extends BaseActivity {
Loading
@@ -158,12 +242,30 @@ public class AddUserActivity extends BaseActivity {
ButterKnife.bind(this); ButterKnife.bind(this);
mProjectId = getIntent().getLongExtra(KEY_PROJECT_ID, -1); mProjectId = getIntent().getLongExtra(KEY_PROJECT_ID, -1);
mGroup = Parcels.unwrap(getIntent().getParcelableExtra(KEY_GROUP)); mGroup = Parcels.unwrap(getIntent().getParcelableExtra(KEY_GROUP));
mUserRoleDialog = new UserRoleDialog(this, mUserRoleDialogListener); mAccessDialog = new AccessDialog(this, mOnAccessAppliedListener);
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp); mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(mOnBackPressed); mToolbar.setNavigationOnClickListener(mOnBackPressed);
mUserSearch.setOnEditorActionListener(mSearchEditorActionListener); mUserSearch.setOnEditorActionListener(mSearchEditorActionListener);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mUserSearch.addTextChangedListener(mTextWatcher);
mAdapter = new MemberAdapter(mUserClickListener); mUserLinearLayoutManager = new GridLayoutManager(this, 2);
mRecyclerView.setLayoutManager(mUserLinearLayoutManager);
mAdapter = new UsersAdapter(mUserClickListener);
mRecyclerView.setAdapter(mAdapter); mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addOnScrollListener(mOnScrollListener);
morph(mRoot);
}
private void loadData() {
KeyboardUtil.hideKeyboard(AddUserActivity.this);
mSwipeRefreshLayout.setRefreshing(true);
mLoading = true;
GitLabClient.instance().searchUsers(mSearchQuery).enqueue(mUserCallback);
}
private void loadMore() {
mLoading = true;
Timber.d("loadMore " + mNextPageUrl.toString() + " " + mSearchQuery);
GitLabClient.instance().searchUsers(mNextPageUrl.toString(), mSearchQuery).enqueue(mMoreUsersCallback);
} }
} }
package com.commit451.gitlab.activities; package com.commit451.gitlab.activity;
   
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
Loading
Loading
package com.commit451.gitlab.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;
import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.DiffAdapter;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.Diff;
import com.commit451.gitlab.model.api.Project;
import com.commit451.gitlab.model.api.RepositoryCommit;
import org.parceler.Parcels;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
/**
* Shows the lines of a commit aka the diff
*/
public class DiffActivity extends BaseActivity {
private static final String EXTRA_PROJECT = "extra_project";
private static final String EXTRA_COMMIT = "extra_commit";
public static Intent newInstance(Context context, Project project, RepositoryCommit commit) {
Intent intent = new Intent(context, DiffActivity.class);
intent.putExtra(EXTRA_PROJECT, Parcels.wrap(project));
intent.putExtra(EXTRA_COMMIT, Parcels.wrap(commit));
return intent;
}
@Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list) RecyclerView mDiffRecyclerView;
DiffAdapter mDiffAdapter;
@Bind(R.id.message_text) TextView mMessageText;
private Project mProject;
private RepositoryCommit mCommit;
private Callback<List<Diff>> mDiffCallback = new Callback<List<Diff>>() {
@Override
public void onResponse(Response<List<Diff>> response, Retrofit retrofit) {
mSwipeRefreshLayout.setRefreshing(false);
if (!response.isSuccess()) {
return;
}
for (Diff diff : response.body()) {
Timber.d("diff text: "+ diff.getDiff());
}
mDiffAdapter.setData(response.body());
}
@Override
public void onFailure(Throwable t) {
mSwipeRefreshLayout.setRefreshing(false);
Timber.e(t, null);
mMessageText.setText(R.string.connection_error);
mMessageText.setVisibility(View.VISIBLE);
Snackbar.make(getWindow().getDecorView(), getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_diff);
ButterKnife.bind(this);
mProject = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_PROJECT));
mCommit = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_COMMIT));
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mToolbar.setTitle(mCommit.getShortId());
mDiffAdapter = new DiffAdapter(new DiffAdapter.Listener() {
@Override
public void onDiffClicked(Diff diff) {
}
});
mDiffRecyclerView.setAdapter(mDiffAdapter);
mDiffRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadData();
}
});
loadData();
}
private void loadData() {
mMessageText.setVisibility(View.GONE);
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
if (mSwipeRefreshLayout != null) {
mSwipeRefreshLayout.setRefreshing(true);
}
}
});
GitLabClient.instance().getCommitDiff(mProject.getId(), mCommit.getId()).enqueue(mDiffCallback);
}
}
\ No newline at end of file
package com.commit451.gitlab.activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.util.Base64;
import android.view.MenuItem;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.webkit.WebView;
import com.commit451.gitlab.R;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.model.api.RepositoryFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import timber.log.Timber;
public class FileActivity extends BaseActivity {
private static final long MAX_FILE_SIZE = 1024 * 1024;
private static final String EXTRA_PROJECT_ID = "extra_project_id";
private static final String EXTRA_PATH = "extra_path";
private static final String EXTRA_REF = "extra_ref";
public static Intent newIntent(Context context, long projectId, String path, String ref) {
Intent intent = new Intent(context, FileActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_PATH, path);
intent.putExtra(EXTRA_REF, ref);
return intent;
}
@Bind(R.id.toolbar) Toolbar mToolbar;
@Bind(R.id.file_blob) WebView mFileBlobView;
@Bind(R.id.progress) View mProgressView;
private long mProjectId;
private String mPath;
private String mRef;
private String mFileName;
private byte[] mBlob;
private final Callback<RepositoryFile> mFileResponseCallback = new Callback<RepositoryFile>() {
@Override
public void onResponse(Response<RepositoryFile> response, Retrofit retrofit) {
mProgressView.setVisibility(View.GONE);
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
public void onFailure(Throwable t) {
Timber.e(t, null);
mProgressView.setVisibility(View.GONE);
Snackbar.make(getWindow().getDecorView(), R.string.file_load_error, Snackbar.LENGTH_SHORT)
.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
ButterKnife.bind(this);
mProjectId = getIntent().getLongExtra(EXTRA_PROJECT_ID, -1);
mPath = getIntent().getStringExtra(EXTRA_PATH);
mRef = getIntent().getStringExtra(EXTRA_REF);
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_open:
openFile();
return true;
case R.id.action_save:
saveBlob();
return true;
}
return false;
}
});
loadData();
}
private void loadData() {
mProgressView.setVisibility(View.VISIBLE);
GitLabClient.instance().getFile(mProjectId, mPath, mRef).enqueue(mFileResponseCallback);
}
private File saveBlob() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) && mBlob != null) {
File targetFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), mFileName);
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(targetFile);
outputStream.write(mBlob);
Snackbar.make(getWindow().getDecorView(), getString(R.string.file_saved), Snackbar.LENGTH_SHORT)
.show();
return targetFile;
} catch (IOException e) {
Timber.e(e, null);
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
}
}
}
} else {
Snackbar.make(getWindow().getDecorView(), getString(R.string.save_error), Snackbar.LENGTH_SHORT)
.show();
}
return null;
}
private void openFile() {
File file = saveBlob();
if (file == null) {
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show();
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.fromFile(file));
String extension = fileExt(file.getName());
if (extension != null) {
intent.setTypeAndNormalize(MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
}
try {
startActivity(intent);
} catch (ActivityNotFoundException | SecurityException e) {
Timber.e(e, null);
Snackbar.make(getWindow().getDecorView(), getString(R.string.open_error), Snackbar.LENGTH_SHORT)
.show();
}
}
private static String fileExt(String filename) {
int extStart = filename.lastIndexOf(".") + 1;
if (extStart < 1) {
return null;
}
return filename.substring(extStart);
}
}
package com.commit451.gitlab.activities; package com.commit451.gitlab.activity;
   
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
   
import com.commit451.gitlab.tools.NavigationManager; import com.commit451.gitlab.BuildConfig;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.data.Prefs; import com.commit451.gitlab.data.Prefs;
import com.commit451.gitlab.model.Account;
import com.commit451.gitlab.util.NavigationManager;
import java.util.List;
import timber.log.Timber;
   
/** /**
* This activity acts as switching platform for the application directing the user to the appropriate * This activity acts as switching platform for the application directing the user to the appropriate
* activity based on their logged in state * activity based on their logged in state
*
* Created by r0adkll on 9/18/15.
*/ */
public class GitlabActivity extends Activity { public class GitlabActivity extends Activity {
   
Loading
@@ -18,13 +23,28 @@ public class GitlabActivity extends Activity {
Loading
@@ -18,13 +23,28 @@ public class GitlabActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
   
if(!Prefs.isLoggedIn(this)) { int savedVersion = Prefs.getSavedVersion(this);
if (savedVersion != -1 && savedVersion < BuildConfig.VERSION_CODE) {
Timber.d("Performing upgrade");
performUpgrade(savedVersion, BuildConfig.VERSION_CODE);
Prefs.setSavedVersion(this);
}
List<Account> accounts = Account.getAccounts(this);
if(accounts.isEmpty()) {
NavigationManager.navigateToLogin(this); NavigationManager.navigateToLogin(this);
} else { } else {
GitLabClient.setAccount(accounts.get(0));
NavigationManager.navigateToProjects(this); NavigationManager.navigateToProjects(this);
} }
   
// Always finish this activity // Always finish this activity
finish(); finish();
} }
/**
* Perform an upgrade from one version to another. This should only be one time upgrade things
*/
private void performUpgrade(int previousVersion, int currentVersion) {
}
} }
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