├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── dongyue │ │ └── gitlabandroid │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── dongyue │ │ │ └── gitlabandroid │ │ │ ├── App.java │ │ │ ├── activity │ │ │ ├── HomeActivity.java │ │ │ ├── IssueActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MyActivitesActivity.java │ │ │ ├── ProjectActivity.java │ │ │ ├── SettingsActivity.java │ │ │ ├── UserInfoActivity.java │ │ │ ├── WelcomeActivity.java │ │ │ └── base │ │ │ │ ├── AppCompatPreferenceActivity.java │ │ │ │ └── BaseActivity.java │ │ │ ├── adapter │ │ │ ├── FeedAdapter.java │ │ │ ├── IssuesAdapter.java │ │ │ ├── ProjectsAdapter.java │ │ │ └── RepositoryCommitsAdapter.java │ │ │ ├── fragment │ │ │ ├── ActivitiesFragment.java │ │ │ ├── BaseFragment.java │ │ │ ├── OverviewFragment.java │ │ │ ├── ProjectsFragment.java │ │ │ └── RepositoryCommitsFragment.java │ │ │ ├── model │ │ │ ├── Account.java │ │ │ ├── MyIssueInfo.java │ │ │ ├── api │ │ │ │ ├── APIError.java │ │ │ │ ├── Branch.java │ │ │ │ ├── Contributor.java │ │ │ │ ├── Diff.java │ │ │ │ ├── Email.java │ │ │ │ ├── ForkedFromProject.java │ │ │ │ ├── Group.java │ │ │ │ ├── GroupDetail.java │ │ │ │ ├── Identity.java │ │ │ │ ├── Issue.java │ │ │ │ ├── Member.java │ │ │ │ ├── MergeRequest.java │ │ │ │ ├── Milestone.java │ │ │ │ ├── Note.java │ │ │ │ ├── Project.java │ │ │ │ ├── ProjectNamespace.java │ │ │ │ ├── RepositoryCommit.java │ │ │ │ ├── RepositoryFile.java │ │ │ │ ├── RepositoryTreeObject.java │ │ │ │ ├── User.java │ │ │ │ ├── UserBasic.java │ │ │ │ ├── UserFull.java │ │ │ │ ├── UserLogin.java │ │ │ │ └── UserSafe.java │ │ │ ├── db │ │ │ │ └── Activity.java │ │ │ └── rss │ │ │ │ ├── Entry.java │ │ │ │ ├── Feed.java │ │ │ │ ├── Link.java │ │ │ │ └── Thumbnail.java │ │ │ ├── network │ │ │ ├── AuthentificationInterceptor.java │ │ │ ├── ConnectivityHelper.java │ │ │ ├── GitLab.java │ │ │ ├── GitLabRss.java │ │ │ ├── GitlabClient.java │ │ │ └── GitlabSubscriber.java │ │ │ ├── service │ │ │ └── PollingService.java │ │ │ ├── utils │ │ │ ├── ConversionUtil.java │ │ │ ├── Gravatar.java │ │ │ ├── GsonProvider.java │ │ │ ├── ImageUtil.java │ │ │ ├── Logger.java │ │ │ ├── NavigationManager.java │ │ │ ├── ObjectUtil.java │ │ │ ├── OkHttpProvider.java │ │ │ ├── PicassoImageGetter.java │ │ │ ├── Prefs.java │ │ │ ├── SimpleXmlProvider.java │ │ │ ├── ToastUtils.java │ │ │ ├── ViewUtil.java │ │ │ ├── db │ │ │ │ ├── ActivityConverter.java │ │ │ │ └── ActivityDBManager.java │ │ │ └── eventbus │ │ │ │ ├── RxBus.java │ │ │ │ └── events │ │ │ │ ├── APIErrorEvent.java │ │ │ │ ├── CloseDrawerEvent.java │ │ │ │ ├── NewActivitiesEvent.java │ │ │ │ ├── NoNetworkEvent.java │ │ │ │ ├── SwitchBranchEvent.java │ │ │ │ └── UniqueEvent.java │ │ │ └── view │ │ │ ├── BadgeView.java │ │ │ ├── CircleTransformation.java │ │ │ ├── GitlabNavigationView.java │ │ │ ├── GitlabSwipeRefreshLayout.java │ │ │ └── NoScrollViewPager.java │ └── res │ │ ├── anim │ │ ├── do_nothing.xml │ │ ├── fade_in.xml │ │ └── fade_out.xml │ │ ├── drawable-hdpi │ │ ├── ic_file_24dp.xml │ │ ├── ic_folder_24dp.xml │ │ ├── ic_info_black_24dp.png │ │ ├── ic_notifications_black_24dp.png │ │ ├── ic_repo_24dp.xml │ │ ├── ic_sync_black_24dp.png │ │ └── ic_unknown_24dp.xml │ │ ├── drawable-mdpi │ │ ├── ic_info_black_24dp.png │ │ ├── ic_notifications_black_24dp.png │ │ └── ic_sync_black_24dp.png │ │ ├── drawable-v21 │ │ ├── ic_info_black_24dp.xml │ │ ├── ic_notifications_black_24dp.xml │ │ └── ic_sync_black_24dp.xml │ │ ├── drawable-xhdpi │ │ ├── ic_info_black_24dp.png │ │ ├── ic_notifications_black_24dp.png │ │ └── ic_sync_black_24dp.png │ │ ├── drawable-xxhdpi │ │ ├── ic_info_black_24dp.png │ │ ├── ic_notifications_black_24dp.png │ │ └── ic_sync_black_24dp.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_info_black_24dp.png │ │ ├── ic_notifications_black_24dp.png │ │ └── ic_sync_black_24dp.png │ │ ├── drawable │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_home.xml │ │ ├── activity_issue.xml │ │ ├── activity_login.xml │ │ ├── activity_my_activites.xml │ │ ├── activity_project.xml │ │ ├── activity_user_info.xml │ │ ├── activity_welcome.xml │ │ ├── app_bar_home.xml │ │ ├── content_home.xml │ │ ├── content_issue.xml │ │ ├── content_my_activites.xml │ │ ├── content_user_info.xml │ │ ├── fragment_activities.xml │ │ ├── fragment_overview.xml │ │ ├── fragment_project.xml │ │ ├── fragment_project_commits.xml │ │ ├── fragment_projects.xml │ │ ├── item_entry.xml │ │ ├── item_issue.xml │ │ ├── item_project.xml │ │ ├── item_project_commit.xml │ │ ├── nav_header_home.xml │ │ ├── nav_header_issue.xml │ │ ├── simple_list_item_1_dark.xml │ │ └── tab_layout.xml │ │ ├── menu │ │ ├── activity_home_drawer.xml │ │ ├── home.xml │ │ ├── menu_project.xml │ │ └── menu_user_info.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ ├── strings_app.xml │ │ └── styles.xml │ │ └── xml │ │ ├── pref_data_sync.xml │ │ ├── pref_general.xml │ │ ├── pref_headers.xml │ │ └── pref_notification.xml │ └── test │ └── java │ └── io │ └── dongyue │ └── gitlabandroid │ └── ExampleUnitTest.java ├── build.gradle ├── gitlab-android.iml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/* 4 | .DS_Store 5 | /build 6 | /captures 7 | *.iml -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | gitlab-android -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitlab-android 2 | Unofficial GitLab Android client. Support self hosted GitLab and Push notifications 3 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | apply plugin: 'com.neenbedankt.android-apt' 4 | 5 | android { 6 | compileSdkVersion 23 7 | buildToolsVersion "23.0.2" 8 | 9 | defaultConfig { 10 | applicationId "io.dongyue.gitlabandroid" 11 | minSdkVersion 16 12 | targetSdkVersion 23 13 | versionCode 1 14 | versionName "1.0" 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | 30 | ext { 31 | okhttp_version = "2.5.0" 32 | retrofit_version = "2.0.0-beta2" 33 | picasso_version = "2.5.2" 34 | gson_version = "2.4" 35 | junit_version = "4.12" 36 | rx_java_version = "1.0.15" 37 | rx_android_version = "1.1.0" 38 | okhttp_logging_version = "2.7.0" 39 | } 40 | 41 | 42 | dependencies { 43 | compile fileTree(dir: 'libs', include: ['*.jar']) 44 | testCompile 'junit:junit:4.12' 45 | 46 | apt "org.parceler:parceler:1.0.3" 47 | 48 | compile "com.squareup.okhttp:okhttp:$okhttp_version" 49 | 50 | compile "com.squareup.retrofit:retrofit:$retrofit_version" 51 | compile "com.squareup.retrofit:converter-gson:$retrofit_version" 52 | compile ('com.squareup.retrofit:converter-simplexml:2.0.0-beta2') { 53 | exclude group: 'xpp3', module: 'xpp3' 54 | exclude group: 'stax', module: 'stax-api' 55 | exclude group: 'stax', module: 'stax' 56 | } 57 | compile "com.squareup.retrofit:adapter-rxjava:$retrofit_version" 58 | compile "io.reactivex:rxjava:$rx_java_version" 59 | compile "io.reactivex:rxandroid:$rx_android_version" 60 | compile "com.squareup.picasso:picasso:$picasso_version" 61 | compile "com.squareup.okhttp:logging-interceptor:$okhttp_logging_version" 62 | 63 | compile "com.google.code.gson:gson:$gson_version" 64 | 65 | testCompile "junit:junit:$junit_version" 66 | compile 'com.android.support:appcompat-v7:23.1.1' 67 | compile 'com.android.support:design:23.1.1' 68 | compile 'com.jakewharton:butterknife:7.0.1' 69 | compile 'org.parceler:parceler-api:1.0.3' 70 | compile 'com.android.support:support-v4:23.1.1' 71 | compile 'net.danlew:android.joda:2.9.1' 72 | compile 'com.commit451:bypasses:1.0.1' 73 | 74 | compile 'io.requery:requery:1.0.0-beta2' 75 | compile 'io.requery:requery-android:1.0.0-beta2' // for android 76 | apt 'io.requery:requery-processor:1.0.0-beta2' // use an APT plugin 77 | } 78 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in J:\android-sdk-windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/io/dongyue/gitlabandroid/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 22 | 23 | 28 | 29 | 33 | 36 | 37 | 42 | 45 | 46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 61 | 64 | 65 | 70 | 73 | 74 | 79 | 82 | 83 | 84 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/App.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid; 2 | 3 | import android.app.AlarmManager; 4 | import android.app.Application; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import java.util.Calendar; 10 | 11 | import io.dongyue.gitlabandroid.network.GitlabClient; 12 | import io.dongyue.gitlabandroid.service.PollingService; 13 | import io.dongyue.gitlabandroid.utils.OkHttpProvider; 14 | import io.dongyue.gitlabandroid.utils.ToastUtils; 15 | import io.requery.Persistable; 16 | import io.requery.android.sqlite.DatabaseSource; 17 | import io.requery.rx.RxSupport; 18 | import io.requery.rx.SingleEntityStore; 19 | import io.requery.sql.Configuration; 20 | import io.requery.sql.EntityDataStore; 21 | 22 | import io.dongyue.gitlabandroid.model.db.Models; 23 | 24 | /** 25 | * Created by Brotherjing on 2016/3/5. 26 | */ 27 | public class App extends Application { 28 | 29 | private static Context context; 30 | 31 | private static SingleEntityStore dataStore; 32 | 33 | @Override 34 | public void onCreate() { 35 | super.onCreate(); 36 | context = this; 37 | ToastUtils.register(this); 38 | initPollingService(); 39 | } 40 | 41 | public static Context getInstance(){ 42 | return context; 43 | } 44 | 45 | private void initPollingService(){ 46 | Intent intent = PollingService.getPollingIntent(this); 47 | PendingIntent pendingIntent = PendingIntent.getService(this, PollingService.CODE_ACTION_POLL 48 | , intent, PendingIntent.FLAG_UPDATE_CURRENT); 49 | 50 | Calendar calendar = Calendar.getInstance(); 51 | AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); 52 | alarmManager.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis()+60*1000,AlarmManager.INTERVAL_HALF_HOUR,pendingIntent); 53 | } 54 | 55 | public static SingleEntityStore getData() { 56 | if (dataStore == null) { 57 | // override onUpgrade to handle migrating to a new version 58 | DatabaseSource source = new DatabaseSource(context, Models.DEFAULT, 1); 59 | Configuration configuration = source.getConfiguration(); 60 | dataStore = RxSupport.toReactiveStore( 61 | new EntityDataStore(configuration)); 62 | } 63 | return dataStore; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/activity/MyActivitesActivity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.FragmentTransaction; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | 12 | import io.dongyue.gitlabandroid.R; 13 | import io.dongyue.gitlabandroid.fragment.ActivitiesFragment; 14 | 15 | public class MyActivitesActivity extends AppCompatActivity { 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_my_activites); 21 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 22 | setSupportActionBar(toolbar); 23 | 24 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 25 | fab.setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View view) { 28 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 29 | .setAction("Action", null).show(); 30 | } 31 | }); 32 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 33 | 34 | if(savedInstanceState==null){ 35 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 36 | fragmentTransaction.add(R.id.feed_layout, ActivitiesFragment.newInstance(ActivitiesFragment.FEED_TYPE_USER)).commit(); 37 | } 38 | } 39 | 40 | @Override 41 | public boolean onOptionsItemSelected(MenuItem item) { 42 | int id = item.getItemId(); 43 | if (id == android.R.id.home) { 44 | if (!super.onOptionsItemSelected(item)) { 45 | //NavUtils.navigateUpFromSameTask(this); 46 | finish(); 47 | } 48 | return true; 49 | } 50 | return super.onOptionsItemSelected(item); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/activity/UserInfoActivity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.widget.TextView; 11 | 12 | import butterknife.Bind; 13 | import butterknife.ButterKnife; 14 | import io.dongyue.gitlabandroid.R; 15 | import io.dongyue.gitlabandroid.activity.base.BaseActivity; 16 | import io.dongyue.gitlabandroid.model.api.UserFull; 17 | import io.dongyue.gitlabandroid.network.GitlabClient; 18 | import io.dongyue.gitlabandroid.network.GitlabSubscriber; 19 | import rx.Observable; 20 | import rx.android.schedulers.AndroidSchedulers; 21 | import rx.schedulers.Schedulers; 22 | 23 | public class UserInfoActivity extends BaseActivity { 24 | 25 | @Bind(R.id.text) 26 | TextView textView; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_user_info); 32 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 33 | setSupportActionBar(toolbar); 34 | ButterKnife.bind(this); 35 | loadData(); 36 | 37 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 38 | fab.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View view) { 41 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 42 | .setAction("Action", null).show(); 43 | } 44 | }); 45 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 46 | } 47 | 48 | private void loadData(){ 49 | addSubscription(GitlabClient.getInstance().getThisUser() 50 | .subscribeOn(Schedulers.io()) 51 | .observeOn(AndroidSchedulers.mainThread()) 52 | .subscribe(new GitlabSubscriber() { 53 | @Override 54 | public void onNext(UserFull userFull) { 55 | StringBuilder st = new StringBuilder(); 56 | st.append("User name: ").append(userFull.getUsername()) 57 | .append("\nEmail: ").append(userFull.getEmail()) 58 | .append("\nId: ").append(userFull.getId()) 59 | .append("\nCreatedAt: ").append(userFull.getCreatedAt()) 60 | .append("\nProjectsLimit: ").append(userFull.getProjectsLimit()) 61 | .append("\nCurrentSignInAt: ").append(userFull.getCurrentSignInAt()) 62 | .append("\nName: ").append(userFull.getName()) 63 | .append("\nState: ").append(userFull.getState()) 64 | .append("\nColorSchemeId: ").append(userFull.getColorSchemeId()) 65 | .append("\nTwitter: ").append(userFull.getTwitter()) 66 | .append("\nSkype: ").append(userFull.getSkype()) 67 | .append("\nLinkedin: ").append(userFull.getLinkedin()) 68 | .append("\nThemeId: ").append(userFull.getThemeId()) 69 | .append("\nIdentities: ").append(userFull.getIdentities()); 70 | textView.setText(st); 71 | } 72 | })); 73 | } 74 | 75 | @Override 76 | public boolean onOptionsItemSelected(MenuItem item) { 77 | int id = item.getItemId(); 78 | if (id == android.R.id.home) { 79 | if (!super.onOptionsItemSelected(item)) { 80 | //NavUtils.navigateUpFromSameTask(this); 81 | finish(); 82 | } 83 | return true; 84 | } 85 | return super.onOptionsItemSelected(item); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/activity/base/AppCompatPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.activity.base; 2 | 3 | import android.content.res.Configuration; 4 | import android.os.Bundle; 5 | import android.preference.PreferenceActivity; 6 | import android.support.annotation.LayoutRes; 7 | import android.support.annotation.Nullable; 8 | import android.support.v7.app.ActionBar; 9 | import android.support.v7.app.AppCompatDelegate; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.MenuInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | /** 16 | * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls 17 | * to be used with AppCompat. 18 | */ 19 | public abstract class AppCompatPreferenceActivity extends PreferenceActivity { 20 | 21 | private AppCompatDelegate mDelegate; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | getDelegate().installViewFactory(); 26 | getDelegate().onCreate(savedInstanceState); 27 | super.onCreate(savedInstanceState); 28 | } 29 | 30 | @Override 31 | protected void onPostCreate(Bundle savedInstanceState) { 32 | super.onPostCreate(savedInstanceState); 33 | getDelegate().onPostCreate(savedInstanceState); 34 | } 35 | 36 | public ActionBar getSupportActionBar() { 37 | return getDelegate().getSupportActionBar(); 38 | } 39 | 40 | public void setSupportActionBar(@Nullable Toolbar toolbar) { 41 | getDelegate().setSupportActionBar(toolbar); 42 | } 43 | 44 | @Override 45 | public MenuInflater getMenuInflater() { 46 | return getDelegate().getMenuInflater(); 47 | } 48 | 49 | @Override 50 | public void setContentView(@LayoutRes int layoutResID) { 51 | getDelegate().setContentView(layoutResID); 52 | } 53 | 54 | @Override 55 | public void setContentView(View view) { 56 | getDelegate().setContentView(view); 57 | } 58 | 59 | @Override 60 | public void setContentView(View view, ViewGroup.LayoutParams params) { 61 | getDelegate().setContentView(view, params); 62 | } 63 | 64 | @Override 65 | public void addContentView(View view, ViewGroup.LayoutParams params) { 66 | getDelegate().addContentView(view, params); 67 | } 68 | 69 | @Override 70 | protected void onPostResume() { 71 | super.onPostResume(); 72 | getDelegate().onPostResume(); 73 | } 74 | 75 | @Override 76 | protected void onTitleChanged(CharSequence title, int color) { 77 | super.onTitleChanged(title, color); 78 | getDelegate().setTitle(title); 79 | } 80 | 81 | @Override 82 | public void onConfigurationChanged(Configuration newConfig) { 83 | super.onConfigurationChanged(newConfig); 84 | getDelegate().onConfigurationChanged(newConfig); 85 | } 86 | 87 | @Override 88 | protected void onStop() { 89 | super.onStop(); 90 | getDelegate().onStop(); 91 | } 92 | 93 | @Override 94 | protected void onDestroy() { 95 | super.onDestroy(); 96 | getDelegate().onDestroy(); 97 | } 98 | 99 | public void invalidateOptionsMenu() { 100 | getDelegate().invalidateOptionsMenu(); 101 | } 102 | 103 | private AppCompatDelegate getDelegate() { 104 | if (mDelegate == null) { 105 | mDelegate = AppCompatDelegate.create(this, null); 106 | } 107 | return mDelegate; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/activity/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.activity.base; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.MenuItem; 6 | 7 | import rx.Subscription; 8 | import rx.subscriptions.CompositeSubscription; 9 | 10 | /** 11 | * Created by Brotherjing on 2016/3/5. 12 | */ 13 | public class BaseActivity extends AppCompatActivity { 14 | 15 | private CompositeSubscription mCompositeSubscription; 16 | 17 | 18 | public CompositeSubscription getCompositeSubscription() { 19 | if (this.mCompositeSubscription == null) { 20 | this.mCompositeSubscription = new CompositeSubscription(); 21 | } 22 | 23 | return this.mCompositeSubscription; 24 | } 25 | 26 | 27 | public void addSubscription(Subscription s) { 28 | if (this.mCompositeSubscription == null) { 29 | this.mCompositeSubscription = new CompositeSubscription(); 30 | } 31 | 32 | this.mCompositeSubscription.add(s); 33 | } 34 | 35 | 36 | @Override protected void onDestroy() { 37 | super.onDestroy(); 38 | if (this.mCompositeSubscription != null) { 39 | this.mCompositeSubscription.unsubscribe(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/adapter/IssuesAdapter.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.adapter; 2 | 3 | import android.net.Uri; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.util.Pair; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import java.text.SimpleDateFormat; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import butterknife.Bind; 17 | import butterknife.ButterKnife; 18 | import io.dongyue.gitlabandroid.R; 19 | import io.dongyue.gitlabandroid.model.MyIssueInfo; 20 | import io.dongyue.gitlabandroid.model.api.Issue; 21 | import io.dongyue.gitlabandroid.model.api.Project; 22 | import io.dongyue.gitlabandroid.network.GitlabClient; 23 | import io.dongyue.gitlabandroid.view.CircleTransformation; 24 | 25 | public class IssuesAdapter extends RecyclerView.Adapter { 26 | 27 | private List issueInfos; 28 | private OnMyIssueInfoListener listener; 29 | 30 | public IssuesAdapter() { 31 | issueInfos = new ArrayList<>(); 32 | } 33 | 34 | public void add(List list) { 35 | issueInfos.addAll(list); 36 | notifyDataSetChanged(); 37 | } 38 | 39 | public void set(List list) { 40 | issueInfos = list; 41 | notifyDataSetChanged(); 42 | } 43 | 44 | public interface OnMyIssueInfoListener { 45 | void onMyIssueInfoClick(MyIssueInfo issueInfo); 46 | } 47 | 48 | private final View.OnClickListener onClickListener = new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | int pos = (int) v.getTag(R.id.list_position); 52 | if (listener != null) listener.onMyIssueInfoClick(issueInfos.get(pos)); 53 | } 54 | }; 55 | 56 | public void setOnItemClickListener(OnMyIssueInfoListener listener) { 57 | this.listener = listener; 58 | } 59 | 60 | @Override 61 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 62 | IssueViewHolder holder = IssueViewHolder.inflate(parent); 63 | holder.itemView.setOnClickListener(onClickListener); 64 | return holder; 65 | } 66 | 67 | @Override 68 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 69 | MyIssueInfo issueInfo = issueInfos.get(position); 70 | if (holder instanceof IssueViewHolder) { 71 | ((IssueViewHolder) holder).bind(issueInfo); 72 | holder.itemView.setTag(R.id.list_position, position); 73 | } 74 | } 75 | 76 | @Override 77 | public int getItemCount() { 78 | return issueInfos.size(); 79 | } 80 | 81 | } 82 | 83 | class IssueViewHolder extends RecyclerView.ViewHolder { 84 | 85 | public static IssueViewHolder inflate(ViewGroup parent) { 86 | View view = LayoutInflater.from(parent.getContext()) 87 | .inflate(R.layout.item_issue, parent, false); 88 | return new IssueViewHolder(view); 89 | } 90 | 91 | @Bind(R.id.project_title) 92 | TextView projectTitleView; 93 | @Bind(R.id.issue_title) 94 | TextView issueTitleView; 95 | @Bind(R.id.issue_author) 96 | TextView issueAuthorView; 97 | @Bind(R.id.issue_create_time) 98 | TextView issueTimeView; 99 | @Bind(R.id.issue_id) 100 | TextView issueIdView; 101 | 102 | public IssueViewHolder(View itemView) { 103 | super(itemView); 104 | ButterKnife.bind(this, itemView); 105 | } 106 | 107 | public void bind(MyIssueInfo issueInfo) { 108 | Issue issue = issueInfo.getIssue(); 109 | projectTitleView.setText(issueInfo.getProject().getNameWithNamespace()); 110 | issueTitleView.setText(issue.getTitle()); 111 | issueIdView.setText(String.format(issueTitleView.getResources().getString(R.string.issue_id), issue.getIid())); 112 | issueAuthorView.setText(String.format(issueAuthorView.getResources().getString(R.string.issue_author), issue.getAuthor().getName())); 113 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/mm/dd"); 114 | String dateStr = dateFormat.format(issue.getCreatedAt()); 115 | issueTimeView.setText(dateStr); 116 | //TODO: add issue state and label; add links to author and project 117 | } 118 | } -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/adapter/ProjectsAdapter.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.adapter; 2 | 3 | import android.net.Uri; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import butterknife.Bind; 15 | import butterknife.ButterKnife; 16 | import io.dongyue.gitlabandroid.R; 17 | import io.dongyue.gitlabandroid.model.api.Project; 18 | import io.dongyue.gitlabandroid.network.GitlabClient; 19 | import io.dongyue.gitlabandroid.view.CircleTransformation; 20 | 21 | /** 22 | * Created by Brotherjing on 2016/3/5. 23 | */ 24 | public class ProjectsAdapter extends RecyclerView.Adapter{ 25 | 26 | private List projects; 27 | private int page = 1; 28 | private boolean finished; 29 | 30 | private OnProjectListener listener; 31 | 32 | public ProjectsAdapter(){ 33 | projects = new ArrayList<>(); 34 | } 35 | 36 | public void add(List list){ 37 | if(list.isEmpty())finished=true; 38 | projects.addAll(list); 39 | page++; 40 | notifyDataSetChanged(); 41 | } 42 | 43 | public void set(List list){ 44 | projects = list; 45 | page = 1; 46 | finished = false; 47 | notifyDataSetChanged(); 48 | } 49 | 50 | public int getPage() { 51 | return page; 52 | } 53 | 54 | public boolean hasMore() { 55 | return !finished; 56 | } 57 | 58 | public interface OnProjectListener{ 59 | void onProjectClick(Project project); 60 | } 61 | 62 | private final View.OnClickListener onClickListener = new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | int pos = (int)v.getTag(R.id.list_position); 66 | if(listener!=null)listener.onProjectClick(projects.get(pos)); 67 | } 68 | }; 69 | 70 | public void setOnItemClickListener(OnProjectListener listener){ 71 | this.listener = listener; 72 | } 73 | 74 | @Override 75 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 76 | ProjectViewHolder holder = ProjectViewHolder.inflate(parent); 77 | holder.itemView.setOnClickListener(onClickListener); 78 | return holder; 79 | } 80 | 81 | @Override 82 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 83 | Project project = projects.get(position); 84 | if(holder instanceof ProjectViewHolder){ 85 | ((ProjectViewHolder)holder).bind(project); 86 | holder.itemView.setTag(R.id.list_position,position); 87 | } 88 | } 89 | 90 | @Override 91 | public int getItemCount() { 92 | return projects.size(); 93 | } 94 | 95 | } 96 | class ProjectViewHolder extends RecyclerView.ViewHolder{ 97 | 98 | public static ProjectViewHolder inflate(ViewGroup parent){ 99 | View view = LayoutInflater.from(parent.getContext()) 100 | .inflate(R.layout.item_project,parent,false); 101 | return new ProjectViewHolder(view); 102 | } 103 | 104 | @Bind(R.id.project_image)ImageView imageView; 105 | @Bind(R.id.project_title)TextView titleView; 106 | @Bind(R.id.project_description)TextView descView; 107 | 108 | public ProjectViewHolder(View itemView) { 109 | super(itemView); 110 | ButterKnife.bind(this,itemView); 111 | } 112 | 113 | public void bind(Project project){ 114 | if(project.getAvatarUrl()!=null&&!project.getAvatarUrl().equals(Uri.EMPTY)){ 115 | GitlabClient.getPicasso() 116 | .load(project.getAvatarUrl()) 117 | .transform(new CircleTransformation()) 118 | .into(imageView); 119 | }else{ 120 | imageView.setImageResource(android.R.drawable.ic_menu_gallery); 121 | } 122 | titleView.setText(project.getNameWithNamespace()); 123 | descView.setText(project.getDescription()); 124 | } 125 | } -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.fragment; 2 | 3 | import android.support.v4.app.Fragment; 4 | 5 | import rx.Subscription; 6 | import rx.subscriptions.CompositeSubscription; 7 | 8 | /** 9 | * Created by Brotherjing on 2016-01-24. 10 | */ 11 | public class BaseFragment extends Fragment { 12 | 13 | private CompositeSubscription mCompositeSubscription; 14 | 15 | 16 | public CompositeSubscription getCompositeSubscription() { 17 | if (this.mCompositeSubscription == null) { 18 | this.mCompositeSubscription = new CompositeSubscription(); 19 | } 20 | 21 | return this.mCompositeSubscription; 22 | } 23 | 24 | 25 | public void addSubscription(Subscription s) { 26 | if (this.mCompositeSubscription == null) { 27 | this.mCompositeSubscription = new CompositeSubscription(); 28 | } 29 | 30 | this.mCompositeSubscription.add(s); 31 | } 32 | 33 | @Override public void onDestroy() { 34 | super.onDestroy(); 35 | if (this.mCompositeSubscription != null) { 36 | this.mCompositeSubscription.unsubscribe(); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/Account.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.Date; 13 | import java.util.List; 14 | 15 | import io.dongyue.gitlabandroid.model.api.UserFull; 16 | import io.dongyue.gitlabandroid.utils.ObjectUtil; 17 | 18 | public class Account implements Comparable{ 19 | 20 | /*public static List getAccounts(Context context) { 21 | List accounts = new ArrayList<>(Prefs.getAccounts(context)); 22 | Collections.sort(accounts); 23 | Collections.reverse(accounts); 24 | return accounts; 25 | }*/ 26 | 27 | @SerializedName("server_url") 28 | Uri mServerUrl; 29 | @SerializedName("authorization_header") 30 | String mAuthorizationHeader; 31 | @SerializedName("private_token") 32 | String mPrivateToken; 33 | @SerializedName("trusted_certificate") 34 | String mTrustedCertificate; 35 | @SerializedName("user") 36 | UserFull mUser; 37 | @SerializedName("last_used") 38 | Date mLastUsed; 39 | 40 | public Account() {} 41 | 42 | public Uri getServerUrl() { 43 | return mServerUrl; 44 | } 45 | 46 | public void setServerUrl(Uri url) { 47 | mServerUrl = url; 48 | } 49 | 50 | public String getAuthorizationHeader() { 51 | return mAuthorizationHeader; 52 | } 53 | 54 | public void setAuthorizationHeader(String authorizationHeader) { 55 | mAuthorizationHeader = authorizationHeader; 56 | } 57 | 58 | public String getPrivateToken() { 59 | return mPrivateToken; 60 | } 61 | 62 | public void setPrivateToken(String privateToken) { 63 | mPrivateToken = privateToken; 64 | } 65 | 66 | public String getTrustedCertificate() { 67 | return mTrustedCertificate; 68 | } 69 | 70 | public void setTrustedCertificate(String trustedCertificate) { 71 | mTrustedCertificate = trustedCertificate; 72 | } 73 | 74 | public UserFull getUser() { 75 | return mUser; 76 | } 77 | 78 | public void setUser(UserFull user) { 79 | mUser = user; 80 | } 81 | 82 | public Date getLastUsed() { 83 | return mLastUsed; 84 | } 85 | 86 | public void setLastUsed(Date lastUsed) { 87 | mLastUsed = lastUsed; 88 | } 89 | 90 | @Override 91 | public int compareTo(@NonNull Account another) { 92 | return mLastUsed.compareTo(another.getLastUsed()); 93 | } 94 | 95 | @Override 96 | public boolean equals(Object o) { 97 | if (!(o instanceof Account)) { 98 | return false; 99 | } 100 | 101 | Account account = (Account) o; 102 | return ObjectUtil.equals(mServerUrl, account.mServerUrl) 103 | && ObjectUtil.equals(mUser, account.mUser); 104 | } 105 | 106 | @Override 107 | public int hashCode() { 108 | return ObjectUtil.hash(mServerUrl, mUser); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/MyIssueInfo.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model; 2 | 3 | import io.dongyue.gitlabandroid.model.api.Issue; 4 | import io.dongyue.gitlabandroid.model.api.Project; 5 | 6 | /** 7 | * Created by Vincent on 16/3/11. 8 | */ 9 | public class MyIssueInfo implements Comparable { 10 | private Issue issue; 11 | private Project project; 12 | 13 | public MyIssueInfo(Issue issue, Project project) { 14 | this.issue = issue; 15 | this.project = project; 16 | } 17 | 18 | public Issue getIssue() { 19 | return issue; 20 | } 21 | 22 | public Project getProject() { 23 | return project; 24 | } 25 | 26 | public int compareTo(MyIssueInfo issueInfo) { 27 | return issue.getCreatedAt().compareTo(issueInfo.issue.getCreatedAt()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/APIError.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by Brotherjing on 2016/3/8. 7 | */ 8 | public class APIError { 9 | 10 | @SerializedName("message") 11 | String message; 12 | 13 | public APIError() { 14 | } 15 | 16 | public String getMessage() { 17 | return message; 18 | } 19 | 20 | public void setMessage(String message) { 21 | this.message = message; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Branch.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import io.dongyue.gitlabandroid.utils.ObjectUtil; 6 | 7 | public class Branch { 8 | @SerializedName("name") 9 | String mName; 10 | @SerializedName("protected") 11 | boolean mProtected; 12 | 13 | public Branch() {} 14 | 15 | public String getName() { 16 | return mName; 17 | } 18 | 19 | public boolean isProtected() { 20 | return mProtected; 21 | } 22 | 23 | @Override 24 | public boolean equals(Object o) { 25 | if (!(o instanceof Branch)) { 26 | return false; 27 | } 28 | 29 | Branch branch = (Branch) o; 30 | return ObjectUtil.equals(mName, branch.mName); 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return ObjectUtil.hash(mName); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return mName; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Contributor.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | 6 | import java.util.ArrayList; 7 | import java.util.LinkedHashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | import io.dongyue.gitlabandroid.utils.ObjectUtil; 12 | 13 | public class Contributor { 14 | @SerializedName("name") 15 | String mName; 16 | @SerializedName("email") 17 | String mEmail; 18 | @SerializedName("commits") 19 | int mCommits; 20 | @SerializedName("additions") 21 | int mAdditions; 22 | @SerializedName("deletions") 23 | int mDeletions; 24 | 25 | public Contributor() {} 26 | 27 | public String getName() { 28 | return mName; 29 | } 30 | 31 | public String getEmail() { 32 | return mEmail; 33 | } 34 | 35 | public int getCommits() { 36 | return mCommits; 37 | } 38 | 39 | public int getAdditions() { 40 | return mAdditions; 41 | } 42 | 43 | public int getDeletions() { 44 | return mDeletions; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object o) { 49 | if (!(o instanceof Contributor)) { 50 | return false; 51 | } 52 | 53 | Contributor contributor = (Contributor) o; 54 | return ObjectUtil.equals(mName, contributor.mName) && ObjectUtil.equals(mEmail, contributor.mEmail); 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return ObjectUtil.hash(mName, mEmail); 60 | } 61 | 62 | public static List groupContributors(List contributors) { 63 | Set contributorEntries = new LinkedHashSet<>(); 64 | for (Contributor contributor : contributors) { 65 | ContributorEntry contrib = null; 66 | for (ContributorEntry entry : contributorEntries) { 67 | if ((contributor.mName != null && contributor.mName.equals(entry.mContributor.mName)) 68 | || (contributor.mEmail != null && contributor.mEmail.equals(entry.mContributor.mEmail))) { 69 | 70 | while (entry.mReplacement != null) { 71 | entry = entry.mReplacement; 72 | } 73 | 74 | if (contrib == entry) { 75 | continue; 76 | } 77 | 78 | if (contrib == null) { 79 | contrib = entry; 80 | } else { 81 | contrib.mContributor.mCommits += entry.mContributor.mCommits; 82 | contrib.mContributor.mAdditions += entry.mContributor.mAdditions; 83 | contrib.mContributor.mDeletions += entry.mContributor.mDeletions; 84 | 85 | entry.mReplacement = contrib; 86 | } 87 | } 88 | } 89 | 90 | if (contrib == null) { 91 | contrib = new ContributorEntry(); 92 | contrib.mContributor = contributor; 93 | 94 | contributorEntries.add(contrib); 95 | } else { 96 | contrib.mContributor.mCommits += contributor.mCommits; 97 | contrib.mContributor.mAdditions += contributor.mAdditions; 98 | contrib.mContributor.mDeletions += contributor.mDeletions; 99 | } 100 | } 101 | 102 | contributors = new ArrayList<>(); 103 | 104 | for (ContributorEntry entry : contributorEntries) { 105 | if (entry.mReplacement == null) { 106 | contributors.add(entry.mContributor); 107 | } 108 | } 109 | 110 | return contributors; 111 | } 112 | 113 | private static class ContributorEntry { 114 | Contributor mContributor; 115 | ContributorEntry mReplacement; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Diff.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Diff { 6 | @SerializedName("old_path") 7 | String mOldPath; 8 | @SerializedName("new_path") 9 | String mNewPath; 10 | @SerializedName("a_mode") 11 | int mAMode; 12 | @SerializedName("b_mode") 13 | int mBMode; 14 | @SerializedName("diff") 15 | String mDiff; 16 | @SerializedName("new_file") 17 | boolean mNewFile; 18 | @SerializedName("renamed_file") 19 | boolean mRenamedFile; 20 | @SerializedName("deleted_file") 21 | boolean mDeletedFile; 22 | 23 | public Diff() {} 24 | 25 | public String getOldPath() { 26 | return mOldPath; 27 | } 28 | 29 | public String getNewPath() { 30 | return mNewPath; 31 | } 32 | 33 | public int getAMode() { 34 | return mAMode; 35 | } 36 | 37 | public int getBMode() { 38 | return mBMode; 39 | } 40 | 41 | public String getDiff() { 42 | return mDiff; 43 | } 44 | 45 | public boolean isNewFile() { 46 | return mNewFile; 47 | } 48 | 49 | public boolean isRenamedFile() { 50 | return mRenamedFile; 51 | } 52 | 53 | public boolean isDeletedFile() { 54 | return mDeletedFile; 55 | } 56 | 57 | public String getFileName() { 58 | if (mNewPath.contains("/")) { 59 | String[] paths = mNewPath.split("/"); 60 | return paths[paths.length-1]; 61 | } else { 62 | return mNewPath; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Email.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Email { 6 | @SerializedName("id") 7 | long mId; 8 | @SerializedName("email") 9 | String mEmail; 10 | 11 | public Email() {} 12 | 13 | public long getId() { 14 | return mId; 15 | } 16 | 17 | public String getEmail() { 18 | return mEmail; 19 | } 20 | 21 | @Override 22 | public boolean equals(Object o) { 23 | if (!(o instanceof Email)) { 24 | return false; 25 | } 26 | 27 | Email email = (Email) o; 28 | return mId == email.mId; 29 | } 30 | 31 | @Override 32 | public int hashCode() { 33 | return (int) (mId ^ (mId >>> 32)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/ForkedFromProject.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import org.parceler.Parcel; 6 | 7 | @Parcel 8 | public class ForkedFromProject { 9 | @SerializedName("id") 10 | long mId; 11 | @SerializedName("name") 12 | String mName; 13 | @SerializedName("name_with_namespace") 14 | String mNameWithNamespace; 15 | @SerializedName("path") 16 | String mPath; 17 | @SerializedName("path_with_namespace") 18 | String mPathWithNamespace; 19 | 20 | public ForkedFromProject() {} 21 | 22 | public long getId() { 23 | return mId; 24 | } 25 | 26 | public String getName() { 27 | return mName; 28 | } 29 | 30 | public String getNameWithNamespace() { 31 | return mNameWithNamespace; 32 | } 33 | 34 | public String getPath() { 35 | return mPath; 36 | } 37 | 38 | public String getPathWithNamespace() { 39 | return mPathWithNamespace; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (!(o instanceof ForkedFromProject)) { 45 | return false; 46 | } 47 | 48 | ForkedFromProject that = (ForkedFromProject) o; 49 | return mId == that.mId; 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | return (int) (mId ^ (mId >>> 32)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Group.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | public class Group { 9 | @SerializedName("id") 10 | long mId; 11 | @SerializedName("name") 12 | String mName; 13 | @SerializedName("path") 14 | String mPath; 15 | @SerializedName("description") 16 | String mDescription; 17 | @SerializedName("avatar_url") 18 | Uri mAvatarUrl; 19 | @SerializedName("web_url") 20 | Uri mWebUrl; 21 | 22 | public Group() {} 23 | 24 | public long getId() { 25 | return mId; 26 | } 27 | 28 | public String getName() { 29 | return mName; 30 | } 31 | 32 | public String getPath() { 33 | return mPath; 34 | } 35 | 36 | public String getDescription() { 37 | return mDescription; 38 | } 39 | 40 | public Uri getAvatarUrl() { 41 | return mAvatarUrl; 42 | } 43 | 44 | public Uri getWebUrl() { 45 | return mWebUrl; 46 | } 47 | 48 | @Nullable 49 | public Uri getFeedUrl() { 50 | if (mWebUrl == null) { 51 | return null; 52 | } 53 | 54 | return Uri.parse(mWebUrl.toString() + ".atom"); 55 | } 56 | 57 | @Override 58 | public boolean equals(Object o) { 59 | if (!(o instanceof Group)) { 60 | return false; 61 | } 62 | 63 | Group group = (Group) o; 64 | return mId == group.mId; 65 | } 66 | 67 | @Override 68 | public int hashCode() { 69 | return (int) (mId ^ (mId >>> 32)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/GroupDetail.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.List; 6 | 7 | public class GroupDetail extends Group { 8 | @SerializedName("projects") 9 | List mProjects; 10 | 11 | public GroupDetail() {} 12 | 13 | public List getProjects() { 14 | return mProjects; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Identity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Identity { 6 | @SerializedName("provider") 7 | String mProvider; 8 | @SerializedName("extern_uid") 9 | String mExternUid; 10 | 11 | public Identity() {} 12 | 13 | public String getProvider() { 14 | return mProvider; 15 | } 16 | 17 | public String getExternUid() { 18 | return mExternUid; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Issue.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | import android.support.annotation.StringDef; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | public class Issue { 14 | public static final String STATE_REOPEN = "reopen"; 15 | public static final String STATE_CLOSE = "close"; 16 | 17 | @StringDef({STATE_REOPEN, STATE_CLOSE}) 18 | @Retention(RetentionPolicy.SOURCE) 19 | public @interface EditState {} 20 | 21 | @SerializedName("id") 22 | long mId; 23 | @SerializedName("iid") 24 | long mIid; 25 | @SerializedName("project_id") 26 | long mProjectId; 27 | @SerializedName("title") 28 | String mTitle; 29 | @SerializedName("description") 30 | String mDescription; 31 | @SerializedName("state") 32 | State mState; 33 | @SerializedName("created_at") 34 | Date mCreatedAt; 35 | @SerializedName("updated_at") 36 | Date mUpdatedAt; 37 | @SerializedName("labels") 38 | List mLabels; 39 | @SerializedName("milestone") 40 | Milestone mMilestone; 41 | @SerializedName("assignee") 42 | UserBasic mAssignee; 43 | @SerializedName("author") 44 | UserBasic mAuthor; 45 | 46 | public Issue() {} 47 | 48 | public long getId() { 49 | return mId; 50 | } 51 | 52 | public long getIid() { 53 | return mIid; 54 | } 55 | 56 | public long getProjectId() { 57 | return mProjectId; 58 | } 59 | 60 | public String getTitle() { 61 | return mTitle; 62 | } 63 | 64 | public String getDescription() { 65 | return mDescription; 66 | } 67 | 68 | public State getState() { 69 | return mState; 70 | } 71 | 72 | public Date getCreatedAt() { 73 | return mCreatedAt; 74 | } 75 | 76 | public Date getUpdatedAt() { 77 | return mUpdatedAt; 78 | } 79 | 80 | public List getLabels() { 81 | return mLabels; 82 | } 83 | 84 | public Milestone getMilestone() { 85 | return mMilestone; 86 | } 87 | 88 | public UserBasic getAssignee() { 89 | return mAssignee; 90 | } 91 | 92 | public UserBasic getAuthor() { 93 | return mAuthor; 94 | } 95 | 96 | public Uri getUrl(Project project) { 97 | return project.getWebUrl().buildUpon() 98 | .appendPath("issues") 99 | .appendPath(Long.toString(getId())) 100 | .build(); 101 | } 102 | 103 | @Override 104 | public boolean equals(Object o) { 105 | if (!(o instanceof Issue)) { 106 | return false; 107 | } 108 | 109 | Issue issue = (Issue) o; 110 | return mId == issue.mId; 111 | } 112 | 113 | @Override 114 | public int hashCode() { 115 | return (int) (mId ^ (mId >>> 32)); 116 | } 117 | 118 | public enum State { 119 | @SerializedName("opened") 120 | OPENED, 121 | @SerializedName("reopened") 122 | REOPENED, 123 | @SerializedName("closed") 124 | CLOSED 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Member.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Member extends UserBasic { 6 | @SerializedName("access_level") 7 | int mAccessLevel; 8 | 9 | public Member() {} 10 | 11 | public int getAccessLevel() { 12 | return mAccessLevel; 13 | } 14 | 15 | public static int getAccessLevel(String accessLevel) { 16 | switch (accessLevel.toLowerCase()) { 17 | case "guest": 18 | return 10; 19 | case "reporter": 20 | return 20; 21 | case "developer": 22 | return 30; 23 | case "master": 24 | return 40; 25 | case "owner": 26 | return 50; 27 | } 28 | 29 | throw new IllegalStateException("No known code for this access level"); 30 | } 31 | 32 | public static String getAccessLevel(int accessLevel) { 33 | switch (accessLevel) { 34 | case 10: 35 | return "Guest"; 36 | case 20: 37 | return "Reporter"; 38 | case 30: 39 | return "Developer"; 40 | case 40: 41 | return "Master"; 42 | case 50: 43 | return "Owner"; 44 | } 45 | 46 | return "Unknown"; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return getUsername(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/MergeRequest.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.Date; 6 | import java.util.List; 7 | public class MergeRequest { 8 | @SerializedName("id") 9 | long mId; 10 | @SerializedName("iid") 11 | long mIid; 12 | @SerializedName("project_id") 13 | long mProjectId; 14 | @SerializedName("title") 15 | String mTitle; 16 | @SerializedName("description") 17 | String mDescription; 18 | @SerializedName("state") 19 | State mState; 20 | @SerializedName("updated_at") 21 | Date mUpdatedAt; 22 | @SerializedName("created_at") 23 | Date mCreatedAt; 24 | @SerializedName("target_branch") 25 | String mTargetBranch; 26 | @SerializedName("source_branch") 27 | String mSourceBranch; 28 | @SerializedName("upvotes") 29 | long mUpvotes; 30 | @SerializedName("downvotes") 31 | long mDownvotes; 32 | @SerializedName("author") 33 | UserBasic mAuthor; 34 | @SerializedName("assignee") 35 | UserBasic mAssignee; 36 | @SerializedName("source_project_id") 37 | long mSourceProjectId; 38 | @SerializedName("target_project_id") 39 | long mTargetProjectId; 40 | @SerializedName("labels") 41 | List mLabels; 42 | @SerializedName("work_in_progress") 43 | boolean mWorkInProgress; 44 | @SerializedName("milestone") 45 | Milestone mMilestone; 46 | @SerializedName("merge_when_build_succeeds") 47 | boolean mMergeWhenBuildSucceeds; 48 | 49 | public MergeRequest() {} 50 | 51 | public long getId() { 52 | return mId; 53 | } 54 | 55 | public long getIid() { 56 | return mIid; 57 | } 58 | 59 | public long getProjectId() { 60 | return mProjectId; 61 | } 62 | 63 | public String getTitle() { 64 | return mTitle; 65 | } 66 | 67 | public String getDescription() { 68 | return mDescription; 69 | } 70 | 71 | public State getState() { 72 | return mState; 73 | } 74 | 75 | public Date getUpdatedAt() { 76 | return mUpdatedAt; 77 | } 78 | 79 | public Date getCreatedAt() { 80 | return mCreatedAt; 81 | } 82 | 83 | public String getTargetBranch() { 84 | return mTargetBranch; 85 | } 86 | 87 | public String getSourceBranch() { 88 | return mSourceBranch; 89 | } 90 | 91 | public long getUpvotes() { 92 | return mUpvotes; 93 | } 94 | 95 | public long getDownvotes() { 96 | return mDownvotes; 97 | } 98 | 99 | public UserBasic getAuthor() { 100 | return mAuthor; 101 | } 102 | 103 | public UserBasic getAssignee() { 104 | return mAssignee; 105 | } 106 | 107 | public long getSourceProjectId() { 108 | return mSourceProjectId; 109 | } 110 | 111 | public long getTargetProjectId() { 112 | return mTargetProjectId; 113 | } 114 | 115 | public List getLabels() { 116 | return mLabels; 117 | } 118 | 119 | public boolean isWorkInProgress() { 120 | return mWorkInProgress; 121 | } 122 | 123 | public Milestone getMilestone() { 124 | return mMilestone; 125 | } 126 | 127 | public boolean isMergeWhenBuildSucceedsEnabled() { 128 | return mMergeWhenBuildSucceeds; 129 | } 130 | 131 | @Override 132 | public boolean equals(Object o) { 133 | if (!(o instanceof MergeRequest)) { 134 | return false; 135 | } 136 | 137 | MergeRequest mergeRequest = (MergeRequest) o; 138 | return mId == mergeRequest.mId; 139 | } 140 | 141 | @Override 142 | public int hashCode() { 143 | return (int) (mId ^ (mId >>> 32)); 144 | } 145 | 146 | public enum State { 147 | @SerializedName("opened") 148 | OPENED, 149 | @SerializedName("merged") 150 | MERGED, 151 | @SerializedName("closed") 152 | CLOSED 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Milestone.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.support.annotation.StringDef; 5 | import android.text.TextUtils; 6 | 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.text.ParseException; 13 | import java.text.SimpleDateFormat; 14 | import java.util.Date; 15 | import java.util.Locale; 16 | 17 | public class Milestone { 18 | public static final String STATE_REOPEN = "reopen"; 19 | public static final String STATE_CLOSE = "close"; 20 | 21 | @StringDef({STATE_REOPEN, STATE_CLOSE}) 22 | @Retention(RetentionPolicy.SOURCE) 23 | public @interface EditState {} 24 | 25 | public static final SimpleDateFormat DUE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-d", Locale.US); 26 | 27 | @SerializedName("id") 28 | long mId; 29 | @SerializedName("iid") 30 | long mIid; 31 | @SerializedName("project_id") 32 | long mProjectId; 33 | @SerializedName("title") 34 | String mTitle; 35 | @SerializedName("description") 36 | String mDescription; 37 | @SerializedName("state") 38 | State mState; 39 | @SerializedName("created_at") 40 | Date mCreatedAt; 41 | @SerializedName("updated_at") 42 | Date mUpdatedAt; 43 | @SerializedName("due_date") 44 | String mDueDate; 45 | 46 | public Milestone() {} 47 | 48 | public long getId() { 49 | return mId; 50 | } 51 | 52 | public long getIid() { 53 | return mIid; 54 | } 55 | 56 | public long getProjectId() { 57 | return mProjectId; 58 | } 59 | 60 | public String getTitle() { 61 | return mTitle; 62 | } 63 | 64 | public String getDescription() { 65 | return mDescription; 66 | } 67 | 68 | public State getState() { 69 | return mState; 70 | } 71 | 72 | public Date getCreatedAt() { 73 | return mCreatedAt; 74 | } 75 | 76 | public Date getUpdatedAt() { 77 | return mUpdatedAt; 78 | } 79 | 80 | @Nullable 81 | public Date getDueDate() { 82 | if (TextUtils.isEmpty(mDueDate)) { 83 | return null; 84 | } 85 | try { 86 | return DUE_DATE_FORMAT.parse(mDueDate); 87 | } catch (ParseException e) { 88 | } 89 | return null; 90 | } 91 | 92 | @Override 93 | public boolean equals(Object o) { 94 | if (!(o instanceof Milestone)) { 95 | return false; 96 | } 97 | 98 | Milestone milestone = (Milestone) o; 99 | return mId == milestone.mId; 100 | } 101 | 102 | @Override 103 | public int hashCode() { 104 | return (int) (mId ^ (mId >>> 32)); 105 | } 106 | 107 | @Override 108 | public String toString() { 109 | return mTitle; 110 | } 111 | 112 | public enum State { 113 | @SerializedName("opened") 114 | OPENED, 115 | @SerializedName("reopened") 116 | REOPENED, 117 | @SerializedName("closed") 118 | CLOSED 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/Note.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.Date; 6 | 7 | public class Note { 8 | @SerializedName("id") 9 | long mId; 10 | @SerializedName("body") 11 | String mBody; 12 | @SerializedName("author") 13 | UserBasic mAuthor; 14 | @SerializedName("created_at") 15 | Date mCreatedAt; 16 | @SerializedName("system") 17 | boolean mSystem; 18 | @SerializedName("noteable_id") 19 | long mNoteableId; 20 | @SerializedName("noteable_type") 21 | Type mNoteableType; 22 | @SerializedName("upvote") 23 | boolean mUpvote; 24 | @SerializedName("downvote") 25 | boolean mDownvote; 26 | 27 | public Note() {} 28 | 29 | public long getId() { 30 | return mId; 31 | } 32 | 33 | public String getBody() { 34 | return mBody; 35 | } 36 | 37 | public UserBasic getAuthor() { 38 | return mAuthor; 39 | } 40 | 41 | public Date getCreatedAt() { 42 | return mCreatedAt; 43 | } 44 | 45 | public boolean isSystem() { 46 | return mSystem; 47 | } 48 | 49 | public long getNoteableId() { 50 | return mNoteableId; 51 | } 52 | 53 | public Type getNoteableType() { 54 | return mNoteableType; 55 | } 56 | 57 | public boolean isUpvote() { 58 | return mUpvote; 59 | } 60 | 61 | public boolean isDownvote() { 62 | return mDownvote; 63 | } 64 | 65 | @Override 66 | public boolean equals(Object o) { 67 | if (!(o instanceof Note)) { 68 | return false; 69 | } 70 | 71 | Note note = (Note) o; 72 | return mId == note.mId; 73 | } 74 | 75 | @Override 76 | public int hashCode() { 77 | return (int) (mId ^ (mId >>> 32)); 78 | } 79 | 80 | public enum Type { 81 | @SerializedName("Issue") 82 | ISSUE, 83 | @SerializedName("MergeRequest") 84 | MERGE_REQUEST 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/ProjectNamespace.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | 8 | import org.parceler.Parcel; 9 | 10 | import java.util.Date; 11 | 12 | @Parcel 13 | public class ProjectNamespace { 14 | @SerializedName("id") 15 | long mId; 16 | @SerializedName("name") 17 | String mName; 18 | @SerializedName("path") 19 | String mPath; 20 | @SerializedName("owner_id") 21 | long mOwnerId; 22 | @SerializedName("created_at") 23 | Date mCreatedAt; 24 | @SerializedName("updated_at") 25 | Date mUpdatedAt; 26 | @SerializedName("description") 27 | String mDescription; 28 | @SerializedName("avatar") 29 | Avatar mAvatar; 30 | @SerializedName("public") 31 | boolean mPublic; 32 | 33 | public ProjectNamespace() {} 34 | 35 | public long getId() { 36 | return mId; 37 | } 38 | 39 | public String getName() { 40 | return mName; 41 | } 42 | 43 | public String getPath() { 44 | return mPath; 45 | } 46 | 47 | public long getOwnerId() { 48 | return mOwnerId; 49 | } 50 | 51 | public Date getCreatedAt() { 52 | return mCreatedAt; 53 | } 54 | 55 | public Date getUpdatedAt() { 56 | return mUpdatedAt; 57 | } 58 | 59 | public String getDescription() { 60 | return mDescription; 61 | } 62 | 63 | public Avatar getAvatar() { 64 | return mAvatar; 65 | } 66 | 67 | public boolean isPublic() { 68 | return mPublic; 69 | } 70 | 71 | @Override 72 | public boolean equals(Object o) { 73 | if (!(o instanceof ProjectNamespace)) { 74 | return false; 75 | } 76 | 77 | ProjectNamespace that = (ProjectNamespace) o; 78 | return mId == that.mId; 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | return (int) (mId ^ (mId >>> 32)); 84 | } 85 | 86 | @Parcel 87 | public static class Avatar { 88 | @SerializedName("url") 89 | Uri mUrl; 90 | 91 | public Avatar() {} 92 | 93 | public Uri getUrl() { 94 | return mUrl; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/RepositoryCommit.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.Date; 6 | 7 | import io.dongyue.gitlabandroid.utils.ObjectUtil; 8 | 9 | public class RepositoryCommit { 10 | @SerializedName("id") 11 | String mId; 12 | @SerializedName("short_id") 13 | String mShortId; 14 | @SerializedName("title") 15 | String mTitle; 16 | @SerializedName("author_name") 17 | String mAuthorName; 18 | @SerializedName("author_email") 19 | String mAuthorEmail; 20 | @SerializedName("created_at") 21 | Date mCreatedAt; 22 | @SerializedName("message") 23 | String mMessage; 24 | 25 | public RepositoryCommit() {} 26 | 27 | public String getId() { 28 | return mId; 29 | } 30 | 31 | public String getShortId() { 32 | return mShortId; 33 | } 34 | 35 | public String getTitle() { 36 | return mTitle; 37 | } 38 | 39 | public String getAuthorName() { 40 | return mAuthorName; 41 | } 42 | 43 | public String getAuthorEmail() { 44 | return mAuthorEmail; 45 | } 46 | 47 | public Date getCreatedAt() { 48 | return mCreatedAt; 49 | } 50 | 51 | public String getMessage() { 52 | return mMessage; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object o) { 57 | if (!(o instanceof RepositoryCommit)) { 58 | return false; 59 | } 60 | 61 | RepositoryCommit commit = (RepositoryCommit) o; 62 | return ObjectUtil.equals(mId, commit.mId); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return ObjectUtil.hash(mId); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/RepositoryFile.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.graphics.RectF; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | public class RepositoryFile { 8 | @SerializedName("file_name") 9 | String mFileName; 10 | @SerializedName("file_path") 11 | String mFilePath; 12 | @SerializedName("size") 13 | long mSize; 14 | @SerializedName("encoding") 15 | String mEncoding; 16 | @SerializedName("content") 17 | String mContent; 18 | @SerializedName("ref") 19 | String mRef; 20 | @SerializedName("blob_id") 21 | String mBlobId; 22 | @SerializedName("commit_id") 23 | String mCommitId; 24 | @SerializedName("last_commit_id") 25 | String mLastCommitId; 26 | 27 | public RepositoryFile() {} 28 | 29 | static public RepositoryFile empty(){ 30 | RepositoryFile repositoryFile = new RepositoryFile(); 31 | repositoryFile.mContent = ""; 32 | return repositoryFile; 33 | } 34 | 35 | public String getFileName() { 36 | return mFileName; 37 | } 38 | 39 | public String getFilePath() { 40 | return mFilePath; 41 | } 42 | 43 | public long getSize() { 44 | return mSize; 45 | } 46 | 47 | public String getEncoding() { 48 | return mEncoding; 49 | } 50 | 51 | public String getContent() { 52 | return mContent; 53 | } 54 | 55 | public String getRef() { 56 | return mRef; 57 | } 58 | 59 | public String getBlobId() { 60 | return mBlobId; 61 | } 62 | 63 | public String getCommitId() { 64 | return mCommitId; 65 | } 66 | 67 | public String getLastCommitId() { 68 | return mLastCommitId; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/RepositoryTreeObject.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import org.parceler.Parcel; 8 | 9 | import io.dongyue.gitlabandroid.R; 10 | 11 | @Parcel 12 | public class RepositoryTreeObject { 13 | @SerializedName("id") 14 | String mId; 15 | @SerializedName("name") 16 | String mName; 17 | @SerializedName("type") 18 | Type mType; 19 | @SerializedName("mode") 20 | String mMode; 21 | 22 | public RepositoryTreeObject() {} 23 | 24 | public String getId() { 25 | return mId; 26 | } 27 | 28 | public String getName() { 29 | return mName; 30 | } 31 | 32 | public Type getType() { 33 | return mType; 34 | } 35 | 36 | public String getMode() { 37 | return mMode; 38 | } 39 | 40 | public int getDrawableForType() { 41 | if (mType == null) { 42 | return R.drawable.ic_unknown_24dp; 43 | } 44 | switch (mType) { 45 | case FILE: 46 | return R.drawable.ic_file_24dp; 47 | case FOLDER: 48 | return R.drawable.ic_folder_24dp; 49 | case REPO: 50 | return R.drawable.ic_repo_24dp; 51 | } 52 | 53 | return R.drawable.ic_unknown_24dp; 54 | } 55 | 56 | public Uri getUrl(Project project, String branchName, String currentPath) { 57 | return project.getWebUrl().buildUpon() 58 | .appendPath("tree") 59 | .appendPath(branchName) 60 | .appendEncodedPath(currentPath) 61 | .appendPath(mName) 62 | .build(); 63 | } 64 | 65 | public enum Type { 66 | @SerializedName("tree") 67 | FOLDER, 68 | @SerializedName("submodule") 69 | REPO, 70 | @SerializedName("blob") 71 | FILE 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/User.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import java.util.Date; 8 | 9 | public class User extends UserBasic { 10 | @SerializedName("created_at") 11 | Date mCreatedAt; 12 | @SerializedName("is_admin") 13 | boolean mIsAdmin; 14 | @SerializedName("bio") 15 | String mBio; 16 | @SerializedName("skype") 17 | String mSkype; 18 | @SerializedName("linkedin") 19 | String mLinkedin; 20 | @SerializedName("twitter") 21 | String mTwitter; 22 | @SerializedName("website_url") 23 | Uri mWebsiteUrl; 24 | 25 | public User() {} 26 | 27 | public Date getCreatedAt() { 28 | return mCreatedAt; 29 | } 30 | 31 | public boolean isAdmin() { 32 | return mIsAdmin; 33 | } 34 | 35 | public String getBio() { 36 | return mBio; 37 | } 38 | 39 | public String getSkype() { 40 | return mSkype; 41 | } 42 | 43 | public String getLinkedin() { 44 | return mLinkedin; 45 | } 46 | 47 | public String getTwitter() { 48 | return mTwitter; 49 | } 50 | 51 | public Uri getWebsiteUrl() { 52 | return mWebsiteUrl; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/UserBasic.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import android.net.Uri; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | import org.parceler.Parcel; 9 | 10 | @Parcel 11 | public class UserBasic extends UserSafe { 12 | @SerializedName("id") 13 | long mId; 14 | @SerializedName("state") 15 | State mState; 16 | @SerializedName("avatar_url") 17 | Uri mAvatarUrl; 18 | @SerializedName("web_url") 19 | Uri mWebUrl; 20 | 21 | public UserBasic() {} 22 | 23 | public long getId() { 24 | return mId; 25 | } 26 | 27 | public State getState() { 28 | return mState; 29 | } 30 | 31 | public Uri getAvatarUrl() { 32 | return mAvatarUrl; 33 | } 34 | 35 | public Uri getWebUrl() { 36 | return mWebUrl; 37 | } 38 | 39 | @Nullable 40 | public Uri getFeedUrl() { 41 | if (mWebUrl == null) { 42 | return null; 43 | } 44 | return Uri.parse(mWebUrl.toString() + ".atom"); 45 | } 46 | 47 | @Override 48 | public boolean equals(Object o) { 49 | if (!(o instanceof UserBasic)) { 50 | return false; 51 | } 52 | 53 | UserBasic user = (UserBasic) o; 54 | return mId == user.mId; 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return (int) (mId ^ (mId >>> 32)); 60 | } 61 | 62 | public enum State { 63 | @SerializedName("active") 64 | ACTIVE, 65 | @SerializedName("blocked") 66 | BLOCKED 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/UserFull.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | public class UserFull extends User { 9 | @SerializedName("email") 10 | String mEmail; 11 | @SerializedName("theme_id") 12 | int mThemeId; 13 | @SerializedName("color_scheme_id") 14 | int mColorSchemeId; 15 | @SerializedName("projects_limit") 16 | int mProjectsLimit; 17 | @SerializedName("current_sign_in_at") 18 | Date mCurrentSignInAt; 19 | @SerializedName("identities") 20 | List mIdentities; 21 | @SerializedName("can_create_group") 22 | boolean mCanCreateGroup; 23 | @SerializedName("can_create_project") 24 | boolean mCanCreateProject; 25 | @SerializedName("two_factor_enabled") 26 | boolean mTwoFactorEnabled; 27 | 28 | public UserFull() {} 29 | 30 | public String getEmail() { 31 | return mEmail; 32 | } 33 | 34 | public int getThemeId() { 35 | return mThemeId; 36 | } 37 | 38 | public int getColorSchemeId() { 39 | return mColorSchemeId; 40 | } 41 | 42 | public int getProjectsLimit() { 43 | return mProjectsLimit; 44 | } 45 | 46 | public Date getCurrentSignInAt() { 47 | return mCurrentSignInAt; 48 | } 49 | 50 | public List getIdentities() { 51 | return mIdentities; 52 | } 53 | 54 | public boolean canCreateGroup() { 55 | return mCanCreateGroup; 56 | } 57 | 58 | public boolean canCreateProject() { 59 | return mCanCreateProject; 60 | } 61 | 62 | public boolean isTwoFactorEnabled() { 63 | return mTwoFactorEnabled; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/UserLogin.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class UserLogin extends UserFull { 6 | @SerializedName("private_token") 7 | String mPrivateToken; 8 | 9 | public UserLogin() {} 10 | 11 | public String getPrivateToken() { 12 | return mPrivateToken; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/api/UserSafe.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.api; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import org.parceler.Parcel; 6 | 7 | @Parcel 8 | public class UserSafe { 9 | @SerializedName("name") 10 | String mName; 11 | @SerializedName("username") 12 | String mUsername; 13 | 14 | public UserSafe() {} 15 | 16 | public String getName() { 17 | return mName; 18 | } 19 | 20 | public String getUsername() { 21 | return mUsername; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (!(o instanceof UserSafe)) { 27 | return false; 28 | } 29 | 30 | UserSafe user = (UserSafe) o; 31 | return mUsername != null ? mUsername.equals(user.mUsername) : user.mUsername == null; 32 | 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | return mUsername != null ? mUsername.hashCode() : 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/db/Activity.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.db; 2 | 3 | import android.os.Parcelable; 4 | 5 | import java.util.Date; 6 | 7 | import io.requery.Entity; 8 | import io.requery.Generated; 9 | import io.requery.Key; 10 | import io.requery.Persistable; 11 | import rx.Observable; 12 | 13 | /** 14 | * Created by Brotherjing on 2016/3/11. 15 | */ 16 | @Entity 17 | public interface Activity extends Parcelable,Persistable{ 18 | 19 | @Key @Generated 20 | int getId(); 21 | 22 | int getRead(); 23 | 24 | String getLink(); 25 | 26 | String getTitle(); 27 | 28 | String getThumbnail(); 29 | 30 | String getSummary(); 31 | 32 | Date getUpdated(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/rss/Entry.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.rss; 2 | 3 | import org.parceler.Parcel; 4 | import org.simpleframework.xml.Element; 5 | import org.simpleframework.xml.Root; 6 | 7 | import java.util.Date; 8 | 9 | @Parcel 10 | @Root(strict = false) 11 | public class Entry { 12 | @Element(name = "link", required = true) 13 | Link mLink; 14 | @Element(name = "title", required = true) 15 | String mTitle; 16 | @Element(name = "updated", required = true) 17 | Date mUpdated; 18 | @Element(name = "thumbnail", required = true) 19 | Thumbnail mThumbnail; 20 | @Element(name = "summary", required = true) 21 | String mSummary; 22 | 23 | public Entry() {} 24 | 25 | public Link getLink() { 26 | return mLink; 27 | } 28 | 29 | public String getTitle() { 30 | return mTitle; 31 | } 32 | 33 | public Date getUpdated() { 34 | return mUpdated; 35 | } 36 | 37 | public Thumbnail getThumbnail() { 38 | return mThumbnail; 39 | } 40 | 41 | public String getSummary() { 42 | return mSummary; 43 | } 44 | 45 | public void setmLink(Link mLink) { 46 | this.mLink = mLink; 47 | } 48 | 49 | public void setmTitle(String mTitle) { 50 | this.mTitle = mTitle; 51 | } 52 | 53 | public void setmUpdated(Date mUpdated) { 54 | this.mUpdated = mUpdated; 55 | } 56 | 57 | public void setmThumbnail(Thumbnail mThumbnail) { 58 | this.mThumbnail = mThumbnail; 59 | } 60 | 61 | public void setmSummary(String mSummary) { 62 | this.mSummary = mSummary; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/rss/Feed.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.rss; 2 | 3 | import org.parceler.Parcel; 4 | import org.simpleframework.xml.Element; 5 | import org.simpleframework.xml.ElementList; 6 | import org.simpleframework.xml.Root; 7 | 8 | import java.util.List; 9 | 10 | @Parcel 11 | @Root(strict = false) 12 | public class Feed { 13 | @Element(name = "title", required = true) 14 | String mTitle; 15 | @ElementList(name = "entry", required = false, inline = true) 16 | List mEntryList; 17 | 18 | public Feed() {} 19 | 20 | public String getTitle() { 21 | return mTitle; 22 | } 23 | 24 | public List getEntries() { 25 | return mEntryList; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/rss/Link.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.rss; 2 | 3 | import android.net.Uri; 4 | 5 | import org.parceler.Parcel; 6 | import org.simpleframework.xml.Attribute; 7 | import org.simpleframework.xml.Root; 8 | 9 | @Parcel 10 | @Root(strict = false) 11 | public class Link { 12 | @Attribute(name = "href", required = true) 13 | Uri mHref; 14 | 15 | public Link() {} 16 | 17 | public Link(Uri mHref) { 18 | this.mHref = mHref; 19 | } 20 | 21 | public Uri getHref() { 22 | return mHref; 23 | } 24 | 25 | public void setmHref(Uri mHref) { 26 | this.mHref = mHref; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/model/rss/Thumbnail.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.model.rss; 2 | 3 | import android.net.Uri; 4 | 5 | import org.parceler.Parcel; 6 | import org.simpleframework.xml.Attribute; 7 | import org.simpleframework.xml.Root; 8 | 9 | @Parcel 10 | @Root(strict = false) 11 | public class Thumbnail { 12 | @Attribute(name = "url", required = true) 13 | Uri mUrl; 14 | 15 | public Thumbnail() {} 16 | 17 | public Thumbnail(Uri mUrl) { 18 | this.mUrl = mUrl; 19 | } 20 | 21 | public Uri getUrl() { 22 | return mUrl; 23 | } 24 | 25 | public void setmUrl(Uri mUrl) { 26 | this.mUrl = mUrl; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/network/AuthentificationInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.network; 2 | 3 | import com.squareup.okhttp.HttpUrl; 4 | import com.squareup.okhttp.Interceptor; 5 | import com.squareup.okhttp.Request; 6 | import com.squareup.okhttp.Response; 7 | 8 | import java.io.IOException; 9 | 10 | import io.dongyue.gitlabandroid.model.Account; 11 | 12 | /** 13 | * Created by Brotherjing on 2016/3/4. 14 | */ 15 | public class AuthentificationInterceptor implements Interceptor { 16 | 17 | private static final String PRIVATE_TOKEN_GET_PARAMETER = "private_token"; 18 | private static final String PRIVATE_TOKEN_HEADER_FIELD = "PRIVATE-TOKEN"; 19 | 20 | private Account account; 21 | 22 | public AuthentificationInterceptor(Account account) { 23 | this.account = account; 24 | } 25 | 26 | @Override 27 | public Response intercept(Chain chain) throws IOException { 28 | Request request = chain.request(); 29 | // HttpUrl url = request.httpUrl(); 30 | String privateToken =account.getPrivateToken(); 31 | if(privateToken!=null) { 32 | request = request.newBuilder() 33 | .header(PRIVATE_TOKEN_HEADER_FIELD, privateToken) 34 | //.url(url) 35 | .build(); 36 | } 37 | return chain.proceed(request); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/network/ConnectivityHelper.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.network; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * Created by Brotherjing on 2016-01-22. 9 | */ 10 | public class ConnectivityHelper { 11 | 12 | public static int NOT_CONNECTED = 0; 13 | public static int TYPE_MOBILE = 1; 14 | public static int TYPE_WIFI = 2; 15 | 16 | public static boolean isConnected(Context context){ 17 | ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 18 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 19 | return activeNetwork.isConnected(); 20 | } 21 | 22 | public static boolean isWifiConnected(Context context){ 23 | ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 24 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 25 | return activeNetwork.isConnected()&&activeNetwork.getType()==ConnectivityManager.TYPE_WIFI; 26 | } 27 | 28 | public static int getConnectionType(Context context){ 29 | ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 30 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 31 | if(activeNetwork.getType()==ConnectivityManager.TYPE_WIFI)return TYPE_WIFI; 32 | else if(activeNetwork.getType()==ConnectivityManager.TYPE_MOBILE)return TYPE_MOBILE; 33 | else return NOT_CONNECTED; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/network/GitLabRss.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.network; 2 | 3 | import io.dongyue.gitlabandroid.model.rss.Feed; 4 | import retrofit.http.GET; 5 | import retrofit.http.Url; 6 | import rx.Observable; 7 | 8 | public interface GitLabRss { 9 | 10 | String RSS_SUFFIX = "dashboard/projects.atom"; 11 | 12 | @GET 13 | Observable getFeed(@Url String url); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/network/GitlabClient.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.network; 2 | 3 | import com.squareup.picasso.OkHttpDownloader; 4 | import com.squareup.picasso.Picasso; 5 | 6 | import java.util.concurrent.Executor; 7 | import java.util.concurrent.Executors; 8 | 9 | import io.dongyue.gitlabandroid.App; 10 | import io.dongyue.gitlabandroid.model.Account; 11 | import io.dongyue.gitlabandroid.utils.GsonProvider; 12 | import io.dongyue.gitlabandroid.utils.OkHttpProvider; 13 | import io.dongyue.gitlabandroid.utils.Prefs; 14 | import io.dongyue.gitlabandroid.utils.SimpleXmlProvider; 15 | import retrofit.GsonConverterFactory; 16 | import retrofit.Retrofit; 17 | import retrofit.RxJavaCallAdapterFactory; 18 | import retrofit.SimpleXmlConverterFactory; 19 | 20 | /** 21 | * Created by Brotherjing on 2016/3/4. 22 | */ 23 | public class GitlabClient { 24 | 25 | private static Account sAccount; 26 | private static GitLab gitLab; 27 | private static GitLabRss gitLabRss; 28 | 29 | private static Picasso picasso; 30 | 31 | public static void setAccount(Account account){ 32 | sAccount = account; 33 | gitLab = null; 34 | gitLabRss = null; 35 | picasso = null; 36 | } 37 | 38 | public static GitLab getInstance(Account account){ 39 | 40 | if(gitLab==null||!account.equals(sAccount)){ 41 | sAccount = account; 42 | createInstance(); 43 | } 44 | return gitLab; 45 | } 46 | 47 | public static GitLab getInstance(){ 48 | if(sAccount==null){ 49 | sAccount = Prefs.getAccount(App.getInstance()); 50 | } 51 | return getInstance(sAccount); 52 | } 53 | 54 | public static GitLabRss getRssInstance(){ 55 | if(sAccount==null){ 56 | sAccount = Prefs.getAccount(App.getInstance()); 57 | } 58 | if(gitLabRss==null){ 59 | createRssInstance(); 60 | } 61 | return gitLabRss; 62 | } 63 | 64 | public static Picasso getPicasso(){ 65 | if(picasso==null){ 66 | picasso = new Picasso.Builder(App.getInstance()) 67 | .downloader(new OkHttpDownloader(OkHttpProvider.getInstance(sAccount))) 68 | .build(); 69 | } 70 | return picasso; 71 | } 72 | 73 | private static void createRssInstance(){ 74 | Retrofit retrofit = new Retrofit.Builder() 75 | .baseUrl(GitLab.BASE_URL) 76 | .client(OkHttpProvider.getInstance(sAccount)) 77 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 78 | .addConverterFactory(SimpleXmlConverterFactory.create(SimpleXmlProvider.createPersister(sAccount))) 79 | .build(); 80 | gitLabRss = retrofit.create(GitLabRss.class); 81 | } 82 | 83 | private static void createInstance(){ 84 | 85 | Executor executor = Executors.newCachedThreadPool(); 86 | Retrofit retrofit = new Retrofit.Builder() 87 | .baseUrl(GitLab.BASE_URL) 88 | .callbackExecutor(executor) 89 | .addConverterFactory(GsonConverterFactory.create(GsonProvider.createInstance(sAccount))) 90 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 91 | .client(OkHttpProvider.getInstance(sAccount)) 92 | .build(); 93 | 94 | gitLab = retrofit.create(GitLab.class); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/network/GitlabSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.network; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.net.UnknownHostException; 6 | 7 | import io.dongyue.gitlabandroid.R; 8 | import io.dongyue.gitlabandroid.utils.ToastUtils; 9 | import retrofit.HttpException; 10 | import rx.Subscriber; 11 | 12 | /** 13 | * Created by Brotherjing on 2016/3/9. 14 | */ 15 | public abstract class GitlabSubscriber extends Subscriber { 16 | @Override 17 | public void onCompleted() { 18 | 19 | } 20 | 21 | @Override 22 | public void onError(Throwable e) { 23 | if (e instanceof HttpException) { 24 | ToastUtils.showShort("error code " + ((HttpException) e).code()); 25 | }else if(e instanceof UnknownHostException){ 26 | ToastUtils.showShort(R.string.error_unknown_host); 27 | }else{ 28 | ToastUtils.showShort(R.string.error_not_connected); 29 | } 30 | e.printStackTrace(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/ConversionUtil.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.net.Uri; 4 | 5 | 6 | import org.joda.time.DateTime; 7 | import org.joda.time.format.ISODateTimeFormat; 8 | 9 | import java.util.Date; 10 | 11 | import io.dongyue.gitlabandroid.model.Account; 12 | 13 | public final class ConversionUtil { 14 | private ConversionUtil() {} 15 | 16 | 17 | public static String fromDate(Date date) { 18 | return ISODateTimeFormat.dateTime().print(new DateTime(date)); 19 | } 20 | 21 | public static Date toDate(String dateString) { 22 | if (dateString == null || dateString.isEmpty()) { 23 | return null; 24 | } 25 | 26 | return ISODateTimeFormat.dateTimeParser().parseDateTime(dateString).toDate(); 27 | } 28 | 29 | public static String fromUri(Uri uri) { 30 | if (uri == null) { 31 | return null; 32 | } 33 | 34 | return uri.toString(); 35 | } 36 | 37 | public static Uri toUri(Account account, String uriString) { 38 | if (uriString == null) { 39 | return null; 40 | } 41 | if (uriString.isEmpty()) { 42 | return Uri.EMPTY; 43 | } 44 | 45 | Uri uri = Uri.parse(uriString); 46 | if (!uri.isRelative()) { 47 | return uri; 48 | } 49 | 50 | if (account == null) { 51 | return uri; 52 | } 53 | 54 | Uri.Builder builder = account.getServerUrl() 55 | .buildUpon() 56 | .encodedQuery(uri.getEncodedQuery()) 57 | .encodedFragment(uri.getEncodedFragment()); 58 | 59 | if (uri.getPath().startsWith("/")) { 60 | builder.encodedPath(uri.getEncodedPath()); 61 | } else { 62 | builder.appendEncodedPath(uri.getEncodedPath()); 63 | } 64 | 65 | return builder.build(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/GsonProvider.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.net.Uri; 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.GsonBuilder; 7 | import com.google.gson.JsonDeserializationContext; 8 | import com.google.gson.JsonDeserializer; 9 | import com.google.gson.JsonElement; 10 | import com.google.gson.JsonNull; 11 | import com.google.gson.JsonParseException; 12 | import com.google.gson.JsonPrimitive; 13 | import com.google.gson.JsonSerializationContext; 14 | import com.google.gson.JsonSerializer; 15 | 16 | import java.lang.reflect.Type; 17 | import java.util.Date; 18 | 19 | import io.dongyue.gitlabandroid.model.Account; 20 | 21 | /** 22 | * Get a properly configured Gson object 23 | * Created by Jawn on 12/4/2015. 24 | */ 25 | public final class GsonProvider { 26 | 27 | private static Gson sGson; 28 | 29 | private GsonProvider() {} 30 | 31 | public static Gson getInstance() { 32 | if (sGson == null) { 33 | sGson = createInstance(null); 34 | } 35 | return sGson; 36 | } 37 | 38 | public static Gson createInstance(Account account) { 39 | GsonBuilder gsonBuilder = new GsonBuilder(); 40 | gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 41 | gsonBuilder.registerTypeAdapter(Uri.class, new UriSerializer(account)); 42 | return gsonBuilder.create(); 43 | } 44 | 45 | 46 | private static class UriSerializer implements JsonSerializer, JsonDeserializer { 47 | private final Account mAccount; 48 | 49 | public UriSerializer(Account account) { 50 | mAccount = account; 51 | } 52 | 53 | @Override 54 | public Uri deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 55 | String uriString = null; 56 | if (!json.isJsonNull()) { 57 | uriString = json.getAsString(); 58 | } 59 | 60 | return ConversionUtil.toUri(mAccount, uriString); 61 | } 62 | 63 | @Override 64 | public JsonElement serialize(Uri src, Type typeOfSrc, JsonSerializationContext context) { 65 | String uriString = ConversionUtil.fromUri(src); 66 | if (uriString == null) { 67 | return JsonNull.INSTANCE; 68 | } 69 | 70 | return new JsonPrimitive(uriString); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/ImageUtil.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.net.Uri; 4 | 5 | 6 | 7 | /** 8 | * Utility for doing various image related things 9 | * Created by Jawn on 9/20/2015. 10 | */ 11 | public class ImageUtil { 12 | 13 | public static Uri getAvatarUrl(String email, int size) { 14 | return Gravatar 15 | .init(email) 16 | .ssl() 17 | .size(size) 18 | .defaultImage(Gravatar.DefaultImage.IDENTICON) 19 | .build(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/Logger.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by Brotherjing on 2015/9/20. 7 | */ 8 | public class Logger { 9 | 10 | public enum LogLevel{ 11 | FULL, 12 | NONE 13 | } 14 | 15 | private static long timestamp; 16 | 17 | private static LogLevel log_level = LogLevel.FULL; 18 | 19 | private static String getClassName(){ 20 | String result; 21 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[2]; 22 | result = thisMethodStack.getClassName(); 23 | return result.substring(result.lastIndexOf("."),result.length()); 24 | } 25 | 26 | private static String callMethodAndLine(){ 27 | String result = "at "; 28 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[2]; 29 | result += thisMethodStack.getClassName()+"."; 30 | result += thisMethodStack.getMethodName(); 31 | result += "("+thisMethodStack.getFileName(); 32 | result += ":"+thisMethodStack.getLineNumber()+") "; 33 | return result; 34 | } 35 | 36 | public static void i(String msg){ 37 | if(log_level==LogLevel.FULL) 38 | Log.i(getClassName(),callMethodAndLine()+msg); 39 | } 40 | 41 | public static void startTimer(String msg){ 42 | timestamp = System.currentTimeMillis(); 43 | i("0ms "+msg); 44 | } 45 | 46 | public static void pin(String msg){ 47 | i((System.currentTimeMillis()-timestamp)+"ms "+msg); 48 | } 49 | 50 | public static void setLogLevel(LogLevel level){ 51 | log_level = level; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/NavigationManager.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import io.dongyue.gitlabandroid.activity.HomeActivity; 7 | import io.dongyue.gitlabandroid.activity.IssueActivity; 8 | import io.dongyue.gitlabandroid.activity.LoginActivity; 9 | import io.dongyue.gitlabandroid.activity.MyActivitesActivity; 10 | import io.dongyue.gitlabandroid.activity.ProjectActivity; 11 | import io.dongyue.gitlabandroid.activity.SettingsActivity; 12 | import io.dongyue.gitlabandroid.activity.UserInfoActivity; 13 | import io.dongyue.gitlabandroid.model.api.Project; 14 | 15 | /** 16 | * Created by Brotherjing on 2016/3/6. 17 | */ 18 | public class NavigationManager { 19 | 20 | public static void toLogin(Context context){ 21 | context.startActivity(new Intent(context, LoginActivity.class)); 22 | } 23 | 24 | public static void toProject(Context context, Project project){ 25 | context.startActivity(ProjectActivity.viewProject(context,project)); 26 | } 27 | 28 | public static void toProjectList(Context context){ 29 | context.startActivity(new Intent(context, HomeActivity.class)); 30 | } 31 | 32 | public static void toMyActivities(Context context){ 33 | context.startActivity(new Intent(context, MyActivitesActivity.class)); 34 | } 35 | 36 | public static void toIssueList(Context context){ 37 | context.startActivity(new Intent(context, IssueActivity.class)); 38 | } 39 | 40 | public static void toSettings(Context context){ 41 | context.startActivity(new Intent(context, SettingsActivity.class)); 42 | } 43 | 44 | public static void toUserInfo(Context context){ 45 | context.startActivity(new Intent(context, UserInfoActivity.class)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/ObjectUtil.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import java.util.Arrays; 4 | 5 | public final class ObjectUtil { 6 | private ObjectUtil() {} 7 | 8 | public static boolean equals(Object a, Object b) { 9 | return (a == null) ? (b == null) : a.equals(b); 10 | } 11 | 12 | public static int hash(Object... values) { 13 | return Arrays.hashCode(values); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/OkHttpProvider.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.util.Log; 6 | 7 | import com.squareup.okhttp.Interceptor; 8 | import com.squareup.okhttp.OkHttpClient; 9 | import com.squareup.okhttp.Request; 10 | import com.squareup.okhttp.Response; 11 | import com.squareup.okhttp.logging.HttpLoggingInterceptor; 12 | 13 | import java.io.IOException; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | import io.dongyue.gitlabandroid.App; 17 | import io.dongyue.gitlabandroid.R; 18 | import io.dongyue.gitlabandroid.model.Account; 19 | import io.dongyue.gitlabandroid.model.api.APIError; 20 | import io.dongyue.gitlabandroid.network.AuthentificationInterceptor; 21 | import io.dongyue.gitlabandroid.network.ConnectivityHelper; 22 | import io.dongyue.gitlabandroid.utils.eventbus.RxBus; 23 | import io.dongyue.gitlabandroid.utils.eventbus.events.APIErrorEvent; 24 | import io.dongyue.gitlabandroid.utils.eventbus.events.NoNetworkEvent; 25 | import rx.android.schedulers.AndroidSchedulers; 26 | import rx.functions.Action0; 27 | 28 | /** 29 | * Created by Brotherjing on 2016/3/5. 30 | */ 31 | public class OkHttpProvider { 32 | 33 | private static OkHttpClient client; 34 | 35 | public static OkHttpClient getInstance(Account account){ 36 | if(client==null){ 37 | client = new OkHttpClient(); 38 | client.setConnectTimeout(10, TimeUnit.SECONDS); 39 | client.interceptors().add(new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)); 40 | client.networkInterceptors().add(new AuthentificationInterceptor(account)); 41 | client.interceptors().add(mErrorInterceptor); 42 | } 43 | return client; 44 | } 45 | 46 | 47 | private static final Interceptor mErrorInterceptor = new Interceptor() { 48 | @Override 49 | public Response intercept(Chain chain) throws IOException { 50 | 51 | Request request = chain.request(); 52 | if(!ConnectivityHelper.isConnected(App.getInstance())){ 53 | RxBus.getBus().post(new NoNetworkEvent()); 54 | //Log.i("yj",mContext.getResources().getString(R.string.error_not_connected)); 55 | return null; 56 | } 57 | Response response = chain.proceed(request); 58 | if(!response.isSuccessful()){ 59 | //String msg = response.message(); 60 | APIError error = GsonProvider.getInstance().fromJson(response.body().string(),APIError.class); 61 | RxBus.getBus().post(new APIErrorEvent(response.code(),error)); 62 | return null; 63 | } 64 | return response; 65 | } 66 | }; 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/PicassoImageGetter.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.drawable.BitmapDrawable; 6 | import android.graphics.drawable.Drawable; 7 | import android.os.AsyncTask; 8 | import android.widget.TextView; 9 | 10 | import com.squareup.picasso.Picasso; 11 | 12 | import in.uncod.android.bypass.Bypass; 13 | 14 | /** 15 | * Original credits: http://stackoverflow.com/a/25530488/504611 16 | */ 17 | public class PicassoImageGetter implements Bypass.ImageGetter { 18 | 19 | private final Picasso mPicasso; 20 | private final TextView mTextView; 21 | private int maxWidth = -1; 22 | 23 | public PicassoImageGetter(final TextView textView, final Picasso picasso) { 24 | mTextView = textView; 25 | mPicasso = picasso; 26 | } 27 | 28 | @Override 29 | public Drawable getDrawable(String source) { 30 | 31 | final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder(); 32 | 33 | final String finalSource = source; 34 | new AsyncTask() { 35 | 36 | @Override 37 | protected Bitmap doInBackground(final Void... meh) { 38 | try { 39 | return mPicasso.load(finalSource).get(); 40 | } catch (Exception e) { 41 | return null; 42 | } 43 | } 44 | 45 | @Override 46 | protected void onPostExecute(final Bitmap bitmap) { 47 | try { 48 | if (maxWidth == -1) { 49 | int horizontalPadding = mTextView.getPaddingLeft() + mTextView.getPaddingRight(); 50 | maxWidth = mTextView.getMeasuredWidth() - horizontalPadding; 51 | if (maxWidth == 0) { 52 | maxWidth = Integer.MAX_VALUE; 53 | } 54 | } 55 | 56 | final BitmapDrawable drawable = new BitmapDrawable(mTextView.getResources(), bitmap); 57 | final double aspectRatio = 1.0 * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight(); 58 | final int width = Math.min(maxWidth, drawable.getIntrinsicWidth()); 59 | final int height = (int) (width / aspectRatio); 60 | 61 | drawable.setBounds(0, 0, width, height); 62 | 63 | result.setDrawable(drawable); 64 | result.setBounds(0, 0, width, height); 65 | 66 | mTextView.setText(mTextView.getText()); // invalidate() doesn't work correctly... 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | 72 | }.execute((Void) null); 73 | 74 | return result; 75 | } 76 | 77 | private static class BitmapDrawablePlaceHolder extends BitmapDrawable { 78 | 79 | protected Drawable drawable; 80 | 81 | @Override 82 | public void draw(final Canvas canvas) { 83 | if (drawable != null) { 84 | drawable.draw(canvas); 85 | } 86 | } 87 | 88 | public void setDrawable(Drawable drawable) { 89 | this.drawable = drawable; 90 | } 91 | 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/Prefs.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.preference.PreferenceManager; 6 | import android.text.TextUtils; 7 | 8 | import io.dongyue.gitlabandroid.model.Account; 9 | 10 | /** 11 | * Created by Brotherjing on 2016/3/5. 12 | */ 13 | public class Prefs { 14 | 15 | private static final String KEY_ACCOUNTS = "accounts"; 16 | 17 | private static SharedPreferences getSharedPrefs(Context context) { 18 | return PreferenceManager.getDefaultSharedPreferences(context); 19 | } 20 | 21 | public static void setAccount(Context context,Account account){ 22 | getSharedPrefs(context) 23 | .edit() 24 | .putString(KEY_ACCOUNTS,GsonProvider.getInstance().toJson(account)) 25 | .commit(); 26 | } 27 | 28 | public static Account getAccount(Context context){ 29 | String json = getSharedPrefs(context).getString(KEY_ACCOUNTS,null); 30 | if(!TextUtils.isEmpty(json)){ 31 | return GsonProvider.getInstance().fromJson(json,Account.class); 32 | }else{ 33 | return new Account(); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/SimpleXmlProvider.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.net.Uri; 4 | 5 | import org.simpleframework.xml.core.Persister; 6 | import org.simpleframework.xml.transform.Matcher; 7 | import org.simpleframework.xml.transform.Transform; 8 | 9 | import java.util.Date; 10 | 11 | import io.dongyue.gitlabandroid.model.Account; 12 | 13 | public final class SimpleXmlProvider { 14 | private static Persister sPersister; 15 | 16 | private SimpleXmlProvider() {} 17 | 18 | public static Persister getPersister() { 19 | if (sPersister == null) { 20 | sPersister = createPersister(null); 21 | } 22 | return sPersister; 23 | } 24 | 25 | public static Persister createPersister(final Account account) { 26 | return new Persister(new Matcher() { 27 | @Override 28 | public Transform match(Class type) throws Exception { 29 | if (Date.class.isAssignableFrom(type)) { 30 | return new DateTransform(account); 31 | } else if (Uri.class.isAssignableFrom(type)) { 32 | return new UriTransform(account); 33 | } 34 | 35 | return null; 36 | } 37 | }); 38 | } 39 | 40 | private static class DateTransform implements Transform { 41 | private final Account mAccount; 42 | 43 | public DateTransform(Account account) { 44 | mAccount = account; 45 | } 46 | 47 | @Override 48 | public Date read(String value) throws Exception { 49 | return ConversionUtil.toDate(value); 50 | } 51 | 52 | @Override 53 | public String write(Date value) throws Exception { 54 | return ConversionUtil.fromDate(value); 55 | } 56 | } 57 | 58 | private static class UriTransform implements Transform { 59 | private final Account mAccount; 60 | 61 | public UriTransform(Account account) { 62 | mAccount = account; 63 | } 64 | 65 | @Override 66 | public Uri read(String value) throws Exception { 67 | return ConversionUtil.toUri(mAccount, value); 68 | } 69 | 70 | @Override 71 | public String write(Uri value) throws Exception { 72 | return ConversionUtil.fromUri(value); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/ToastUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Drakeet 3 | * 4 | * This file is part of Meizhi 5 | * 6 | * Meizhi is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Meizhi is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Meizhi. If not, see . 18 | */ 19 | 20 | package io.dongyue.gitlabandroid.utils; 21 | 22 | import android.content.Context; 23 | import android.widget.Toast; 24 | 25 | /** 26 | * Created by drakeet on 9/27/14. 27 | */ 28 | public class ToastUtils { 29 | 30 | public static Context sContext; 31 | 32 | 33 | private ToastUtils() { 34 | } 35 | 36 | 37 | public static void register(Context context) { 38 | sContext = context.getApplicationContext(); 39 | } 40 | 41 | 42 | private static void check() { 43 | if (sContext == null) { 44 | throw new NullPointerException( 45 | "Must initial call ToastUtils.register(Context context) in your " + 46 | ""); 48 | } 49 | } 50 | 51 | 52 | public static void showShort(int resId) { 53 | check(); 54 | Toast.makeText(sContext, resId, Toast.LENGTH_SHORT).show(); 55 | } 56 | 57 | 58 | public static void showShort(String message) { 59 | check(); 60 | Toast.makeText(sContext, message, Toast.LENGTH_SHORT).show(); 61 | } 62 | 63 | 64 | public static void showLong(int resId) { 65 | check(); 66 | Toast.makeText(sContext, resId, Toast.LENGTH_LONG).show(); 67 | } 68 | 69 | 70 | public static void showLong(String message) { 71 | check(); 72 | Toast.makeText(sContext, message, Toast.LENGTH_LONG).show(); 73 | } 74 | 75 | 76 | public static void showLongX2(String message) { 77 | showLong(message); 78 | showLong(message); 79 | } 80 | 81 | 82 | public static void showLongX2(int resId) { 83 | showLong(resId); 84 | showLong(resId); 85 | } 86 | 87 | 88 | public static void showLongX3(int resId) { 89 | showLong(resId); 90 | showLong(resId); 91 | showLong(resId); 92 | } 93 | 94 | 95 | public static void showLongX3(String message) { 96 | showLong(message); 97 | showLong(message); 98 | showLong(message); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/ViewUtil.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.util.TypedValue; 5 | 6 | import io.dongyue.gitlabandroid.App; 7 | 8 | /** 9 | * Created by Brotherjing on 2016/3/18. 10 | */ 11 | public class ViewUtil { 12 | 13 | public static int dp2px(int dp){ 14 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, App.getInstance().getResources().getDisplayMetrics()); 15 | } 16 | 17 | public static int sp2px(int sp){ 18 | return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, App.getInstance().getResources().getDisplayMetrics()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/db/ActivityConverter.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.db; 2 | 3 | import android.net.Uri; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import io.dongyue.gitlabandroid.App; 9 | import io.dongyue.gitlabandroid.model.db.Activity; 10 | import io.dongyue.gitlabandroid.model.db.ActivityEntity; 11 | import io.dongyue.gitlabandroid.model.rss.Entry; 12 | import io.dongyue.gitlabandroid.model.rss.Feed; 13 | import io.dongyue.gitlabandroid.model.rss.Link; 14 | import io.dongyue.gitlabandroid.model.rss.Thumbnail; 15 | import io.dongyue.gitlabandroid.utils.Logger; 16 | 17 | /** 18 | * Created by Brotherjing on 2016/3/11. 19 | */ 20 | public class ActivityConverter { 21 | 22 | public static ActivityEntity toEntity(Entry entry,boolean read){ 23 | ActivityEntity activityEntity = new ActivityEntity(); 24 | activityEntity.setLink(entry.getLink().getHref().toString()); 25 | activityEntity.setTitle(entry.getTitle()); 26 | activityEntity.setSummary(entry.getSummary()); 27 | activityEntity.setThumbnail(entry.getThumbnail().getUrl().toString()); 28 | activityEntity.setUpdated(entry.getUpdated()); 29 | activityEntity.setRead(read?0:1); 30 | return activityEntity; 31 | } 32 | 33 | public static Entry toActivity(Activity activity){ 34 | Entry entry = new Entry(); 35 | entry.setmLink(new Link(Uri.parse(activity.getLink()))); 36 | entry.setmSummary(activity.getSummary()); 37 | entry.setmThumbnail(new Thumbnail(Uri.parse(activity.getThumbnail()))); 38 | entry.setmTitle(activity.getTitle()); 39 | entry.setmUpdated(activity.getUpdated()); 40 | return entry; 41 | } 42 | 43 | public static List extractNewActivities(Feed feed){ 44 | List list = new ArrayList<>(); 45 | Activity activity = App.getData().select(Activity.class).orderBy(ActivityEntity.UPDATED.desc()).get().firstOrNull(); 46 | //if (activity != null) Logger.i(activity.getUpdated().toString()); 47 | for (Entry entry : feed.getEntries()) { 48 | //Logger.i(entry.getTitle() + " " + entry.getUpdated().toString()); 49 | //Logger.i(activity.getUpdated().toString()+" "+entry.getUpdated().toString()); 50 | if (activity == null || entry.getUpdated().after(activity.getUpdated())) { 51 | list.add(ActivityConverter.toEntity(entry, false)); 52 | } else { 53 | break; 54 | } 55 | } 56 | return list; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/db/ActivityDBManager.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.db; 2 | 3 | import java.util.List; 4 | 5 | import io.dongyue.gitlabandroid.App; 6 | import io.dongyue.gitlabandroid.model.db.Activity; 7 | import io.dongyue.gitlabandroid.model.db.ActivityEntity; 8 | import io.dongyue.gitlabandroid.model.rss.Feed; 9 | import rx.Observable; 10 | 11 | /** 12 | * Created by Brotherjing on 2016/3/18. 13 | */ 14 | public class ActivityDBManager { 15 | 16 | public static final int LIMIT = 20; 17 | 18 | public static Observable> getActivityList(){ 19 | return Observable.just(App.getData().select(Activity.class) 20 | .orderBy(ActivityEntity.UPDATED.desc()) 21 | .limit(LIMIT).get().toList()); 22 | } 23 | 24 | public static Observable> storeActivities(Feed feed){ 25 | List list = ActivityConverter.extractNewActivities(feed); 26 | return App.getData().insert(list).toObservable(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/RxBus.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus; 2 | 3 | import java.util.HashMap; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | import io.dongyue.gitlabandroid.utils.eventbus.events.UniqueEvent; 7 | import rx.Observable; 8 | import rx.subjects.PublishSubject; 9 | import rx.subjects.SerializedSubject; 10 | import rx.subjects.Subject; 11 | 12 | /** 13 | * Created by Brotherjing on 2016/3/9. 14 | */ 15 | public class RxBus { 16 | 17 | private static RxBus bus; 18 | //private Subject subject; 19 | private ConcurrentHashMap,Subject> subjectHashMap; 20 | 21 | public static RxBus getBus(){ 22 | if(bus==null){ 23 | bus = new RxBus(); 24 | } 25 | return bus; 26 | } 27 | 28 | private RxBus(){ 29 | //subject = new SerializedSubject<>(PublishSubject.create()); 30 | subjectHashMap = new ConcurrentHashMap<>(); 31 | } 32 | 33 | public void post(E event){ 34 | //subject.onNext(event); 35 | Class clazz = event.getClass(); 36 | Subject subject = subjectHashMap.get(clazz); 37 | if(subject==null){ 38 | subject = new SerializedSubject<>(PublishSubject.create()); 39 | subjectHashMap.put(clazz,subject); 40 | } 41 | subject.onNext(event); 42 | } 43 | 44 | public Observable observeEvents(Class eventClass) { 45 | Subject subject = subjectHashMap.get(eventClass); 46 | if(subject==null){ 47 | subject = new SerializedSubject<>(PublishSubject.create()); 48 | subjectHashMap.put(eventClass,subject); 49 | } 50 | if(eventClass.isAssignableFrom(UniqueEvent.class)&&subject.hasObservers()){ 51 | return Observable.empty();//if the event should only be received by one observer 52 | } 53 | return subject.ofType(eventClass);//pass only events of specified type, filter all other 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/APIErrorEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | import io.dongyue.gitlabandroid.model.api.APIError; 4 | 5 | /** 6 | * Created by Brotherjing on 2016/3/9. 7 | */ 8 | public class APIErrorEvent extends UniqueEvent{ 9 | 10 | private int code; 11 | private APIError apiError; 12 | 13 | public APIErrorEvent(int code, APIError apiError) { 14 | this.code = code; 15 | this.apiError = apiError; 16 | } 17 | 18 | public int getCode() { 19 | return code; 20 | } 21 | 22 | public void setCode(int code) { 23 | this.code = code; 24 | } 25 | 26 | public APIError getApiError() { 27 | return apiError; 28 | } 29 | 30 | public void setApiError(APIError apiError) { 31 | this.apiError = apiError; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/CloseDrawerEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | /** 4 | * Created by Brotherjing on 2016/3/9. 5 | */ 6 | public class CloseDrawerEvent extends UniqueEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/NewActivitiesEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | /** 4 | * Created by Brotherjing on 2016/3/11. 5 | */ 6 | public class NewActivitiesEvent { 7 | 8 | private int count; 9 | 10 | public NewActivitiesEvent(int count) { 11 | this.count = count; 12 | } 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/NoNetworkEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | /** 4 | * Created by Brotherjing on 2016/3/9. 5 | */ 6 | public class NoNetworkEvent extends UniqueEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/SwitchBranchEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | /** 4 | * Created by Brotherjing on 2016/4/29. 5 | */ 6 | public class SwitchBranchEvent { 7 | 8 | private String branchName; 9 | 10 | public SwitchBranchEvent(String branchName) { 11 | this.branchName = branchName; 12 | } 13 | 14 | public String getBranchName() { 15 | return branchName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/utils/eventbus/events/UniqueEvent.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.utils.eventbus.events; 2 | 3 | /** 4 | * Created by Brotherjing on 2016/3/9. 5 | */ 6 | public abstract class UniqueEvent { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/view/BadgeView.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.text.TextPaint; 9 | import android.util.AttributeSet; 10 | import android.view.View; 11 | 12 | import io.dongyue.gitlabandroid.R; 13 | 14 | /** 15 | * Created by Brotherjing on 2015/8/3. 16 | */ 17 | public class BadgeView extends View { 18 | 19 | private int badgeColor; 20 | private int badgeSize; 21 | private int badgeNum; 22 | private boolean showBackground; 23 | 24 | private Paint mPaint; 25 | private TextPaint mTextPaint; 26 | 27 | public BadgeView(Context context) { 28 | //super(context); 29 | this(context,null); 30 | } 31 | 32 | public BadgeView(Context context, AttributeSet attrs) { 33 | //super(context, attrs); 34 | this(context,attrs,0); 35 | } 36 | 37 | public BadgeView(Context context, AttributeSet attrs, int defStyleAttr) { 38 | super(context, attrs, defStyleAttr); 39 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BadgeView); 40 | int n = ta.getIndexCount(); 41 | for(int i=0;i99)canvas.drawText("99+",badgeSize/2,baseline,mTextPaint); 84 | else canvas.drawText(badgeNum+"",badgeSize/2,baseline,mTextPaint); 85 | } 86 | 87 | public void setBadgeNum(int number){ 88 | badgeNum = number; 89 | postInvalidate(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/view/CircleTransformation.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.view; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Matrix; 7 | import android.graphics.Paint; 8 | 9 | import com.squareup.picasso.Transformation; 10 | 11 | /** 12 | * Copyright (C) 2015 Wasabeef 13 | *

14 | * Licensed under the Apache License, Version 2.0 (the "License"); 15 | * you may not use this file except in compliance with the License. 16 | * You may obtain a copy of the License at 17 | *

18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | *

20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | */ 26 | 27 | /** 28 | * https://github.com/wasabeef/picasso-transformations/blob/master/transformations/src/main/java/jp/wasabeef/picasso/transformations/CropCircleTransformation.java 29 | */ 30 | public class CircleTransformation implements Transformation { 31 | 32 | @Override 33 | public Bitmap transform(Bitmap source) { 34 | if (source == null || (source.getWidth() == 0 && source.getHeight() == 0)) { 35 | return source; 36 | } 37 | int size = Math.min(source.getWidth(), source.getHeight()); 38 | 39 | int width = (source.getWidth() - size) / 2; 40 | int height = (source.getHeight() - size) / 2; 41 | 42 | Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); 43 | 44 | Canvas canvas = new Canvas(bitmap); 45 | Paint paint = new Paint(); 46 | BitmapShader shader = 47 | new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); 48 | if (width != 0 || height != 0) { 49 | // source isn't square, move viewport to center 50 | Matrix matrix = new Matrix(); 51 | matrix.setTranslate(-width, -height); 52 | shader.setLocalMatrix(matrix); 53 | } 54 | paint.setShader(shader); 55 | paint.setAntiAlias(true); 56 | 57 | float r = size / 2f; 58 | canvas.drawCircle(r, r, r, paint); 59 | 60 | source.recycle(); 61 | 62 | return bitmap; 63 | } 64 | 65 | @Override 66 | public String key() { 67 | return "CropCircleTransformation()"; 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/view/GitlabNavigationView.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.view; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.support.design.widget.NavigationView; 6 | import android.util.AttributeSet; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import butterknife.Bind; 13 | import butterknife.ButterKnife; 14 | import io.dongyue.gitlabandroid.R; 15 | import io.dongyue.gitlabandroid.model.api.UserFull; 16 | import io.dongyue.gitlabandroid.network.GitlabClient; 17 | import io.dongyue.gitlabandroid.network.GitlabSubscriber; 18 | import io.dongyue.gitlabandroid.utils.NavigationManager; 19 | import io.dongyue.gitlabandroid.utils.eventbus.RxBus; 20 | import io.dongyue.gitlabandroid.utils.eventbus.events.CloseDrawerEvent; 21 | import rx.Observable; 22 | import rx.Subscription; 23 | import rx.android.schedulers.AndroidSchedulers; 24 | import rx.schedulers.Schedulers; 25 | 26 | /** 27 | * Created by Brotherjing on 2016/3/6. 28 | */ 29 | public class GitlabNavigationView extends NavigationView { 30 | 31 | @Bind(R.id.imageView) 32 | ImageView imageView; 33 | @Bind(R.id.name) 34 | TextView name; 35 | @Bind(R.id.email) 36 | TextView email; 37 | 38 | Subscription subscription; 39 | 40 | public GitlabNavigationView(Context context) { 41 | super(context); 42 | init(context); 43 | } 44 | 45 | public GitlabNavigationView(Context context, AttributeSet attrs) { 46 | super(context, attrs); 47 | init(context); 48 | } 49 | 50 | public GitlabNavigationView(Context context, AttributeSet attrs, int defStyleAttr) { 51 | super(context, attrs, defStyleAttr); 52 | } 53 | 54 | public void init(Context context){ 55 | inflateMenu(R.menu.activity_home_drawer); 56 | View header = inflateHeaderView(R.layout.nav_header_home); 57 | ButterKnife.bind(this, header); 58 | subscription = GitlabClient.getInstance().getThisUser() 59 | .subscribeOn(Schedulers.io()) 60 | .observeOn(AndroidSchedulers.mainThread()) 61 | .subscribe(new GitlabSubscriber() { 62 | @Override 63 | public void onNext(UserFull userFull) { 64 | name.setText(userFull.getName()); 65 | email.setText(userFull.getEmail()); 66 | GitlabClient.getPicasso().with(context) 67 | .load(userFull.getAvatarUrl()) 68 | .resize(100, 100) //图片大小还未确定 69 | .centerCrop() 70 | .into(imageView); 71 | } 72 | }); 73 | header.setOnClickListener(new OnClickListener() { 74 | @Override 75 | public void onClick(View v) { 76 | NavigationManager.toUserInfo(getContext()); 77 | } 78 | }); 79 | 80 | setNavigationItemSelectedListener(onNavigationItemSelectedListener); 81 | //setSelectedItem(); 82 | } 83 | 84 | @Override 85 | protected void onDetachedFromWindow (){ 86 | super.onDetachedFromWindow(); 87 | if(subscription!=null){ 88 | subscription.unsubscribe(); 89 | } 90 | } 91 | 92 | 93 | private OnNavigationItemSelectedListener onNavigationItemSelectedListener = new OnNavigationItemSelectedListener() { 94 | @Override 95 | public boolean onNavigationItemSelected(MenuItem item) { 96 | switch (item.getItemId()){ 97 | case R.id.nav_activity: 98 | NavigationManager.toMyActivities(getContext());break; 99 | case R.id.nav_issue: 100 | NavigationManager.toIssueList(getContext());break; 101 | case R.id.nav_settings: 102 | NavigationManager.toSettings(getContext());break; 103 | case R.id.nav_quit: 104 | ((Activity)getContext()).finish();break; 105 | default:break; 106 | } 107 | RxBus.getBus().post(new CloseDrawerEvent()); 108 | return true; 109 | } 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/view/GitlabSwipeRefreshLayout.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.view; 2 | 3 | import android.content.Context; 4 | import android.support.v4.widget.SwipeRefreshLayout; 5 | import android.util.AttributeSet; 6 | 7 | import io.dongyue.gitlabandroid.R; 8 | 9 | /** 10 | * Created by Brotherjing on 2016/3/5. 11 | */ 12 | public class GitlabSwipeRefreshLayout extends SwipeRefreshLayout { 13 | 14 | public GitlabSwipeRefreshLayout(Context context) { 15 | super(context); 16 | init(); 17 | } 18 | 19 | public GitlabSwipeRefreshLayout(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | init(); 22 | } 23 | 24 | private void init() { 25 | setColorSchemeResources(R.color.colorPrimary, R.color.colorAccent); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/io/dongyue/gitlabandroid/view/NoScrollViewPager.java: -------------------------------------------------------------------------------- 1 | package io.dongyue.gitlabandroid.view; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * Created by Brotherjing on 2015-11-19. 10 | */ 11 | public class NoScrollViewPager extends ViewPager { 12 | 13 | private boolean isCanScroll = false; 14 | 15 | public NoScrollViewPager(Context context) { 16 | super(context); 17 | } 18 | 19 | public NoScrollViewPager(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | 23 | public void setScanScroll(boolean isCanScroll) { 24 | this.isCanScroll = isCanScroll; 25 | } 26 | 27 | @Override 28 | public void scrollTo(int x, int y) { 29 | super.scrollTo(x, y); 30 | } 31 | 32 | @Override 33 | public boolean onTouchEvent(MotionEvent arg0) { 34 | // TODO Auto-generated method stub 35 | if (isCanScroll) { 36 | return super.onTouchEvent(arg0); 37 | } else { 38 | return false; 39 | } 40 | 41 | } 42 | 43 | @Override 44 | public void setCurrentItem(int item, boolean smoothScroll) { 45 | // TODO Auto-generated method stub 46 | super.setCurrentItem(item, smoothScroll); 47 | } 48 | 49 | @Override 50 | public void setCurrentItem(int item) { 51 | // TODO Auto-generated method stub 52 | super.setCurrentItem(item); 53 | } 54 | 55 | @Override 56 | public boolean onInterceptTouchEvent(MotionEvent arg0) { 57 | // TODO Auto-generated method stub 58 | if (isCanScroll) { 59 | return super.onInterceptTouchEvent(arg0); 60 | } else { 61 | return false; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/res/anim/do_nothing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_file_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_folder_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-hdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_repo_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-hdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_unknown_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-mdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-mdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-mdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_info_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_sync_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxhdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxhdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxxhdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxxhdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyweb/gitlab-android/bd8286ecbd69c3393e1968ce600df158cdbf1ecc/app/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_issue.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 13 | 14 | 16 | 17 | 19 | 20 | 22 | 23 | 27 | 28 | 29 | 30 | 32 | 33 | 39 | 40 | 41 | 42 |