Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Commit451/LabCoat
  • Iktwo/GitLabAndroid
  • jonduran3000/GitLabAndroid
  • steffandroid/GitLabAndroid
  • xiaoyanit/GitLabAndroid
  • scottolcott/GitLabAndroid
  • james.mu/GitLabAndroid
  • pushkarpandey27/GitLabAndroid
  • atomfrede/GitLabAndroid
  • burrito82/GitLabAndroid
  • txlong_onz/GitLabAndroid
  • ricardo.longa/GitLabAndroid
  • rubenroy/GitLabAndroid
  • remy_android/GitLabAndroid
  • mzestars/GitLabAndroid
  • theobisproject/LabCoat
  • tarek360/GitLabAndroid
  • TR4Android/LabCoat
  • lvsmart/LabCoat
  • buddybuild/LabCoat
  • tkuah/LabCoat
  • jay3126/LabCoat
  • rmad17/LabCoat
  • galvatron/LabCoat
  • lijianjian13/LabCoat
  • Cody2333/LabCoat
  • ajtfreitas/LabCoat
  • nestor.lobo/LabCoat
  • Microgamer/LabCoat
  • irvinwang/LabCoat
  • avallete/LabCoat
  • digicazter/LabCoat
  • lovexiaov/LabCoat
  • dineshkarpe/LabCoat
  • bak1an/LabCoat
  • loomis/LabCoat
  • sank20/LabCoat
  • Jawnnyfoo/LabCoat
  • scottyab/LabCoat
  • aleksandar-stefanovic/LabCoat
  • tfontana/LabCoat
  • fuzzmz/LabCoat
  • dipaksavaliya/LabCoat
  • adi.bk/LabCoat
  • andreea.voicu/LabCoat
  • H1ghT0p/LabCoat
  • indritqoku/LabCoat
  • armpogart/LabCoat
  • eyedol/LabCoat
  • khairulnizan/LabCoat
  • vadm.perspectiva/LabCoat
  • yiyoss1986/LabCoat
  • BRoy98/LabCoat
  • satyarth.23/LabCoat
  • victorpe76/LabCoat
  • canhnht/LabCoat
  • jinhu/LabCoat
  • weathery/LabCoat
  • gitlabproject_s/LabCoat
  • tfKamran/LabCoat
  • voxadam/LabCoat
  • nprail/LabCoat
  • terrakok/LabCoat
  • jungletian/LabCoat
  • goldins/LabCoat
  • insanum/LabCoat
  • lzrs/LabCoat
  • shankarg/LabCoat
  • rm3l/LabCoat
  • alamo_dev/LabCoat
  • insomniaqc/LabCoat
  • mrasif/LabCoat
  • Babasile/LabCoat
  • eeyoo/LabCoat
  • ditkin/LabCoat
  • unbubot/LabCoat
  • bschuhm/LabCoat
  • fanticker/LabCoat
  • colorwebdesigner/LabCoat
  • milouse/LabCoat
80 results
Show changes
Commits on Source (3)
Showing
with 197 additions and 500 deletions
Change Log Change Log
========== ==========
   
Version 2.5.0
----------------------------
- Change login to reflect API changes in GitLab
Version 2.4.12 Version 2.4.12
---------------------------- ----------------------------
   
Loading
Loading
debug: true debug: true
components: components:
- build-tools;26.0.1 - build-tools;27.0.0
- platforms;android-26 - platforms;android-27
- extras;google;m2repository
Loading
@@ -4,7 +4,7 @@ buildscript {
Loading
@@ -4,7 +4,7 @@ buildscript {
} }
   
dependencies { dependencies {
classpath 'io.fabric.tools:gradle:1.24.1' classpath 'io.fabric.tools:gradle:1.24.5'
} }
} }
   
Loading
@@ -17,30 +17,24 @@ apply plugin: 'kotlin-android'
Loading
@@ -17,30 +17,24 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'io.fabric' apply plugin: 'io.fabric'
   
def versionMajor = 2
def versionMinor = 4
def versionPatch = 12
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
android { android {
compileSdkVersion 26 compileSdkVersion 27
buildToolsVersion "26.0.1" buildToolsVersion "27.0.0"
   
project.ext { project.ext {
LABCOAT_FABRIC_KEY = project.hasProperty("LABCOAT_FABRIC_KEY") ? project.LABCOAT_FABRIC_KEY : "" LABCOAT_FABRIC_KEY = project.hasProperty("LABCOAT_FABRIC_KEY") ? project.LABCOAT_FABRIC_KEY : ""
KEYSTORE_PATH = project.hasProperty("KEYSTORE_PATH") ? project.KEYSTORE_PATH : " " KEYSTORE_PATH = project.hasProperty("KEYSTORE_PATH") ? project.KEYSTORE_PATH : " "
KEYSTORE_PASSWORD = project.hasProperty("KEYSTORE_PASSWORD") ? project.KEYSTORE_PASSWORD : " " KEYSTORE_PASSWORD = project.hasProperty("KEYSTORE_PASSWORD") ? project.KEYSTORE_PASSWORD : " "
KEYSTORE_ALIAS = project.hasProperty("KEYSTORE_ALIAS") ? project.KEYSTORE_ALIAS : " "
KEY_PASSWORD = project.hasProperty("KEY_PASSWORD") ? project.KEY_PASSWORD : " " KEY_PASSWORD = project.hasProperty("KEY_PASSWORD") ? project.KEY_PASSWORD : " "
} }
   
defaultConfig { defaultConfig {
applicationId "com.commit451.gitlab" applicationId "com.commit451.gitlab"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 26 targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild versionCode 2050000
versionName "${versionMajor}.${versionMinor}.${versionPatch}" versionName "2.5.0"
manifestPlaceholders = [fabric_key: project.ext.LABCOAT_FABRIC_KEY] manifestPlaceholders = [fabric_key: project.ext.LABCOAT_FABRIC_KEY]
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
   
Loading
@@ -64,7 +58,7 @@ android {
Loading
@@ -64,7 +58,7 @@ android {
release { release {
storeFile file(project.ext.KEYSTORE_PATH) storeFile file(project.ext.KEYSTORE_PATH)
storePassword project.ext.KEYSTORE_PASSWORD storePassword project.ext.KEYSTORE_PASSWORD
keyAlias project.ext.KEYSTORE_ALIAS keyAlias "commit451"
keyPassword project.ext.KEY_PASSWORD keyPassword project.ext.KEY_PASSWORD
} }
} }
Loading
@@ -99,17 +93,16 @@ android {
Loading
@@ -99,17 +93,16 @@ android {
} }
   
ext { ext {
supportLibVersion = '26.1.0' supportLibVersion = '27.0.1'
retrofitVersion = '2.3.0' retrofitVersion = '2.3.0'
okHttpVersion = '3.9.0' okHttpVersion = '3.9.1'
butterknifeVersion = '8.8.1' butterknifeVersion = '8.8.1'
parcelerVersion = '1.1.9' parcelerVersion = '1.1.9'
reptarVersion = '2.5.1' reptarVersion = '2.5.1'
adapterLayout = '1.1.1' adapterLayout = '1.1.2'
materialDialogsVersion = '0.9.4.7' materialDialogsVersion = '0.9.5.0'
leakCanaryVersion = '1.5.3' leakCanaryVersion = '1.5.3'
addendumVersion = '1.4.0' addendumVersion = '1.6.0'
alakazamVersion = '1.0.1'
moshiVersion = '1.5.0' moshiVersion = '1.5.0'
} }
   
Loading
@@ -147,15 +140,15 @@ dependencies {
Loading
@@ -147,15 +140,15 @@ dependencies {
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
implementation "com.jakewharton:butterknife:$butterknifeVersion" implementation "com.jakewharton:butterknife:$butterknifeVersion"
kapt "com.jakewharton:butterknife-compiler:$butterknifeVersion" kapt "com.jakewharton:butterknife-compiler:$butterknifeVersion"
implementation 'com.jakewharton.timber:timber:4.5.1' implementation 'com.jakewharton.timber:timber:4.6.0'
implementation 'com.jakewharton.threetenabp:threetenabp:1.0.5' implementation 'com.jakewharton.threetenabp:threetenabp:1.0.5'
   
implementation 'org.greenrobot:eventbus:3.0.0' implementation 'org.greenrobot:eventbus:3.1.1'
   
implementation 'io.reactivex.rxjava2:rxjava:2.1.3' implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
   
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.0' implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
   
implementation "org.parceler:parceler-api:$parcelerVersion" implementation "org.parceler:parceler-api:$parcelerVersion"
kapt "org.parceler:parceler:$parcelerVersion" kapt "org.parceler:parceler:$parcelerVersion"
Loading
@@ -172,21 +165,22 @@ dependencies {
Loading
@@ -172,21 +165,22 @@ dependencies {
implementation("com.wefika:flowlayout:0.4.1") { implementation("com.wefika:flowlayout:0.4.1") {
exclude group: 'com.intellij', module: 'annotations' exclude group: 'com.intellij', module: 'annotations'
} }
implementation 'com.github.Commit451.Easel:easel:2.1.1' implementation 'com.github.Commit451:Easel:3.0.0'
implementation 'com.github.Commit451:Gimbal:2.0.2' implementation 'com.github.Commit451:Gimbal:2.0.2'
implementation 'com.github.Commit451:Teleprinter:1.0.2' implementation 'com.github.Commit451:Teleprinter:1.0.2'
implementation 'com.github.Commit451:Jounce:1.0.2' implementation 'com.github.Commit451:Jounce:1.0.2'
implementation 'com.github.Commit451:ForegroundViews:2.4.0' implementation 'com.github.Commit451:ForegroundViews:2.4.0'
implementation 'com.github.Commit451:MorphTransitions:2.0.0' implementation 'com.github.Commit451:MorphTransitions:2.0.0'
implementation "com.github.Commit451.Alakazam:alakazam:$alakazamVersion" implementation "com.github.Commit451:Alakazam:2.0.0"
implementation "com.github.Commit451.Alakazam:alakazam-kotlin:$alakazamVersion" implementation 'com.github.Commit451:Lift:2.0.1'
implementation 'com.github.Commit451:Lift:1.2.0' implementation 'com.github.Commit451:okyo:3.0.1'
implementation 'com.github.Commit451:okyo:2.0.0'
implementation 'com.github.Commit451:OkioProGuardRules:1.11.0.0' implementation 'com.github.Commit451:OkioProGuardRules:1.11.0.0'
implementation 'com.github.Commit451:RetrofitProguardRules:2.2.0.0' implementation 'com.github.Commit451:RetrofitProguardRules:2.2.0.0'
implementation 'com.github.Commit451:LoganSquareProGuardRules:1.3.7.0' implementation 'com.github.Commit451:LoganSquareProGuardRules:1.3.7.0'
implementation 'com.github.Commit451:EventBusProGuardRules:3.0.0.0' implementation 'com.github.Commit451:EventBusProGuardRules:3.0.0.0'
implementation "com.github.Commit451.Addendum:addendum:$addendumVersion" implementation "com.github.Commit451.Addendum:addendum:$addendumVersion"
implementation "com.github.Commit451.Addendum:addendum-recyclerview:$addendumVersion"
implementation "com.github.Commit451.Addendum:addendum-design:$addendumVersion"
implementation "com.github.Commit451.Addendum:addendum-parceler:$addendumVersion" implementation "com.github.Commit451.Addendum:addendum-parceler:$addendumVersion"
   
implementation 'com.github.chrisbanes:PhotoView:2.1.3' implementation 'com.github.chrisbanes:PhotoView:2.1.3'
Loading
@@ -197,28 +191,28 @@ dependencies {
Loading
@@ -197,28 +191,28 @@ dependencies {
   
implementation 'com.alexgwyn.recyclerviewsquire:recyclerviewsquire:0.0.6' implementation 'com.alexgwyn.recyclerviewsquire:recyclerviewsquire:0.0.6'
   
implementation 'com.github.ivbaranov:materiallettericon:0.2.2' implementation 'com.github.ivbaranov:materiallettericon:0.2.3'
   
implementation 'com.github.alorma:diff-textview:1.3.0' implementation 'com.github.alorma:diff-textview:1.3.0'
   
implementation 'com.wdullaer:materialdatetimepicker:3.3.0' implementation 'com.wdullaer:materialdatetimepicker:3.4.0'
   
implementation 'com.github.novoda:simple-chrome-custom-tabs:0.1.5' implementation 'com.github.novoda:simple-chrome-custom-tabs:0.1.5'
   
implementation "com.afollestad.material-dialogs:core:$materialDialogsVersion" implementation "com.afollestad.material-dialogs:core:$materialDialogsVersion"
implementation "com.afollestad.material-dialogs:commons:$materialDialogsVersion" implementation "com.afollestad.material-dialogs:commons:$materialDialogsVersion"
   
implementation 'de.hdodenhof:circleimageview:2.1.0' implementation 'de.hdodenhof:circleimageview:2.2.0'
   
implementation('com.vdurmont:emoji-java:3.3.0') { implementation('com.vdurmont:emoji-java:4.0.0') {
exclude group: 'org.json', module: 'json' exclude group: 'org.json', module: 'json'
} }
   
implementation 'com.github.jkwiecien:EasyImage:2.0.3' implementation 'com.github.jkwiecien:EasyImage:2.0.4'
   
implementation 'com.atlassian.commonmark:commonmark:0.10.0' implementation 'com.atlassian.commonmark:commonmark:0.10.0'
   
normalImplementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { normalImplementation('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
transitive = true transitive = true
} }
   
Loading
Loading
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commit451.gitlab"> package="com.commit451.gitlab">
   
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   
<application <application
android:name=".App" android:name=".App"
Loading
@@ -13,66 +13,93 @@
Loading
@@ -13,66 +13,93 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name=".activity.LaunchActivity" android:name=".activity.LaunchActivity"
android:theme="@style/Activity.Launch"> android:theme="@style/Activity.Launch">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
   
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".activity.ProjectsActivity" android:name=".activity.ProjectsActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/Activity.Projects"/> android:theme="@style/Activity.Projects" />
<activity <activity
android:name=".activity.GroupsActivity" android:name=".activity.GroupsActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/Activity.Groups"/> android:theme="@style/Activity.Groups" />
<activity <activity
android:name=".activity.ActivityActivity" android:name=".activity.ActivityActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/Activity.Activity"/> android:theme="@style/Activity.Activity" />
<activity <activity
android:name=".activity.TodosActivity" android:name=".activity.TodosActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/Activity.Todos"/> android:theme="@style/Activity.Todos" />
<activity android:name=".activity.ProjectActivity"/>
<activity android:name=".activity.ProjectActivity" />
<activity <activity
android:name=".activity.LoginActivity" android:name=".activity.LoginActivity"
android:theme="@style/Activity.Login"/> android:theme="@style/Activity.Login" />
<activity android:name=".activity.FileActivity"/>
<activity android:name=".activity.IssueActivity"/> <activity android:name=".activity.FileActivity" />
<activity android:name=".activity.DiffActivity"/>
<activity android:name=".activity.AboutActivity"/> <activity android:name=".activity.IssueActivity" />
<activity android:name=".activity.AddUserActivity"/>
<activity android:name=".activity.DiffActivity" />
<activity android:name=".activity.AboutActivity" />
<activity android:name=".activity.AddUserActivity" />
<activity <activity
android:name=".activity.UserActivity" android:name=".activity.UserActivity"
android:theme="@style/Activity.User"/> android:theme="@style/Activity.User" />
<activity android:name=".activity.SearchActivity"/>
<activity android:name=".activity.SearchActivity" />
<activity <activity
android:name=".activity.GroupActivity" android:name=".activity.GroupActivity"
android:theme="@style/Activity.Group"/> android:theme="@style/Activity.Group" />
<activity android:name=".activity.MergeRequestActivity"/>
<activity android:name=".activity.AddIssueActivity"/> <activity android:name=".activity.MergeRequestActivity" />
<activity android:name=".activity.MilestoneActivity"/>
<activity android:name=".activity.AddMilestoneActivity"/> <activity android:name=".activity.AddIssueActivity" />
<activity android:name=".activity.BuildActivity"/>
<activity android:name=".activity.PipelineActivity"/> <activity android:name=".activity.MilestoneActivity" />
<activity android:name=".activity.AddMilestoneActivity" />
<activity android:name=".activity.BuildActivity" />
<activity android:name=".activity.PipelineActivity" />
<activity <activity
android:name=".activity.LoadSomeInfoActivity" android:name=".activity.LoadSomeInfoActivity"
android:theme="@style/Activity.Translucent"/> android:theme="@style/Activity.Translucent" />
<activity android:name=".activity.SettingsActivity"/>
<activity android:name=".activity.AddLabelActivity"/> <activity android:name=".activity.SettingsActivity" />
<activity android:name=".activity.AddNewLabelActivity"/>
<activity android:name=".activity.AddLabelActivity" />
<activity android:name=".activity.AddNewLabelActivity" />
<activity <activity
android:name=".activity.PickBranchOrTagActivity" android:name=".activity.PickBranchOrTagActivity"
android:theme="@style/Activity.Translucent"/> android:theme="@style/Activity.Translucent" />
<activity android:name=".activity.WebLoginActivity"/>
<activity <activity
android:name=".activity.AttachActivity" android:name=".activity.AttachActivity"
android:theme="@style/Activity.Translucent"/> android:theme="@style/Activity.Translucent" />
<activity <activity
android:name=".activity.RoutingActivity" android:name=".activity.RoutingActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
Loading
@@ -81,57 +108,61 @@
Loading
@@ -81,57 +108,61 @@
   
<!-- Standard Url --> <!-- Standard Url -->
<intent-filter android:label="@string/deeplink_text"> <intent-filter android:label="@string/deeplink_text">
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW" />
   
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
   
<data android:scheme="@string/deeplink_scheme"/> <data android:scheme="@string/deeplink_scheme" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".widget.UserFeedWidgetConfigureActivity"> <activity android:name=".widget.UserFeedWidgetConfigureActivity">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".widget.ProjectFeedWidgetConfigureActivity"> <activity android:name=".widget.ProjectFeedWidgetConfigureActivity">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".widget.ProjectFeedWidgetConfigureProjectActivity"/>
   
<activity android:name=".activity.FullscreenImageActivity"/> <activity android:name=".widget.ProjectFeedWidgetConfigureProjectActivity" />
   
<activity android:name=".activity.DebugActivity"/> <activity android:name=".activity.FullscreenImageActivity" />
<activity android:name=".activity.DebugActivity" />
   
<receiver <receiver
android:name=".widget.UserFeedWidgetProvider" android:name=".widget.UserFeedWidgetProvider"
android:label="User Feed"> android:label="User Feed">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter> </intent-filter>
   
<meta-data <meta-data
android:name="android.appwidget.provider" android:name="android.appwidget.provider"
android:resource="@xml/widget_user_feed"/> android:resource="@xml/widget_user_feed" />
</receiver> </receiver>
<receiver <receiver
android:name=".widget.ProjectFeedWidgetProvider" android:name=".widget.ProjectFeedWidgetProvider"
android:label="Project Feed"> android:label="Project Feed">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter> </intent-filter>
   
<meta-data <meta-data
android:name="android.appwidget.provider" android:name="android.appwidget.provider"
android:resource="@xml/widget_project_feed"/> android:resource="@xml/widget_project_feed" />
</receiver> </receiver>
   
<service <service
android:name=".widget.ProjectFeedWidgetService" android:name=".widget.FeedWidgetService"
android:exported="false" android:exported="false"
android:permission="android.permission.BIND_REMOTEVIEWS"/> android:permission="android.permission.BIND_REMOTEVIEWS" />
   
</application> </application>
   
Loading
Loading
Loading
@@ -15,6 +15,7 @@ import butterknife.ButterKnife
Loading
@@ -15,6 +15,7 @@ import butterknife.ButterKnife
import butterknife.OnClick import butterknife.OnClick
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.addendum.themeAttrColor
import com.commit451.easel.Easel import com.commit451.easel.Easel
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
Loading
@@ -83,7 +84,7 @@ class AddMilestoneActivity : MorphActivity() {
Loading
@@ -83,7 +84,7 @@ class AddMilestoneActivity : MorphActivity() {
now.get(Calendar.MONTH), now.get(Calendar.MONTH),
now.get(Calendar.DAY_OF_MONTH) now.get(Calendar.DAY_OF_MONTH)
) )
dpd.accentColor = Easel.getThemeAttrColor(this, R.attr.colorAccent) dpd.accentColor = this.themeAttrColor(R.attr.colorAccent)
dpd.show(fragmentManager, "date_picker") dpd.show(fragmentManager, "date_picker")
} }
   
Loading
Loading
Loading
@@ -15,7 +15,7 @@ import android.widget.EditText
Loading
@@ -15,7 +15,7 @@ import android.widget.EditText
import butterknife.* import butterknife.*
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.alakazam.HideRunnable import com.commit451.alakazam.fadeOut
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
import com.commit451.gitlab.adapter.UserAdapter import com.commit451.gitlab.adapter.UserAdapter
Loading
@@ -96,9 +96,7 @@ class AddUserActivity : MorphActivity() {
Loading
@@ -96,9 +96,7 @@ class AddUserActivity : MorphActivity() {
@OnTextChanged(R.id.search) @OnTextChanged(R.id.search)
fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (s.isNullOrEmpty()) { if (s.isNullOrEmpty()) {
buttonClear.animate() buttonClear.fadeOut()
.alpha(0.0f)
.withEndAction(HideRunnable(buttonClear))
} else { } else {
buttonClear.visibility = View.VISIBLE buttonClear.visibility = View.VISIBLE
buttonClear.animate().alpha(1.0f) buttonClear.animate().alpha(1.0f)
Loading
Loading
Loading
@@ -15,7 +15,7 @@ import butterknife.ButterKnife
Loading
@@ -15,7 +15,7 @@ import butterknife.ButterKnife
import butterknife.OnClick import butterknife.OnClick
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.alakazam.kotlin.fadeIn import com.commit451.alakazam.fadeIn
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
import com.commit451.gitlab.extension.setup import com.commit451.gitlab.extension.setup
Loading
Loading
Loading
@@ -19,7 +19,9 @@ import butterknife.BindView
Loading
@@ -19,7 +19,9 @@ import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.alakazam.Alakazam import com.commit451.addendum.themeAttrColor
import com.commit451.alakazam.navigationBarColorAnimator
import com.commit451.easel.Easel import com.commit451.easel.Easel
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
Loading
@@ -121,22 +123,22 @@ class GroupActivity : BaseActivity() {
Loading
@@ -121,22 +123,22 @@ class GroupActivity : BaseActivity() {
   
fun bindPalette(palette: Palette) { fun bindPalette(palette: Palette) {
val animationTime = 1000 val animationTime = 1000
val vibrantColor = palette.getVibrantColor(Easel.getThemeAttrColor(this, R.attr.colorAccent)) val vibrantColor = palette.getVibrantColor(this.themeAttrColor(R.attr.colorAccent))
val darkerColor = Easel.getDarkerColor(vibrantColor) val darkerColor = Easel.darkerColor(vibrantColor)
   
if (Build.VERSION.SDK_INT >= 21) { if (Build.VERSION.SDK_INT >= 21) {
Alakazam.navigationBarColorAnimator(window, darkerColor) window.navigationBarColorAnimator(darkerColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
} }
   
ObjectAnimator.ofObject(collapsingToolbarLayout, "contentScrimColor", ArgbEvaluator(), ObjectAnimator.ofObject(collapsingToolbarLayout, "contentScrimColor", ArgbEvaluator(),
Easel.getThemeAttrColor(this, R.attr.colorPrimary), vibrantColor) this.themeAttrColor(R.attr.colorPrimary), vibrantColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
   
ObjectAnimator.ofObject(collapsingToolbarLayout, "statusBarScrimColor", ArgbEvaluator(), ObjectAnimator.ofObject(collapsingToolbarLayout, "statusBarScrimColor", ArgbEvaluator(),
Easel.getThemeAttrColor(this, R.attr.colorPrimaryDark), darkerColor) this.themeAttrColor(R.attr.colorPrimaryDark), darkerColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
   
Loading
Loading
Loading
@@ -22,10 +22,6 @@ import com.commit451.gitlab.ssl.CustomKeyManager
Loading
@@ -22,10 +22,6 @@ import com.commit451.gitlab.ssl.CustomKeyManager
class LaunchActivity : BaseActivity() { class LaunchActivity : BaseActivity() {
   
companion object { companion object {
//Figure out how this works, then reenable
private val PRIVATE_KEY_ENABLED = false
private val REQUEST_DEVICE_AUTH = 123 private val REQUEST_DEVICE_AUTH = 123
} }
   
Loading
@@ -57,11 +53,7 @@ class LaunchActivity : BaseActivity() {
Loading
@@ -57,11 +53,7 @@ class LaunchActivity : BaseActivity() {
} else if (Prefs.isRequiredDeviceAuth) { } else if (Prefs.isRequiredDeviceAuth) {
showKeyguard() showKeyguard()
} else { } else {
if (PRIVATE_KEY_ENABLED) { moveAlong()
loadPrivateKey(accounts, 0)
} else {
moveAlong()
}
} }
} }
   
Loading
@@ -80,26 +72,4 @@ class LaunchActivity : BaseActivity() {
Loading
@@ -80,26 +72,4 @@ class LaunchActivity : BaseActivity() {
Navigator.navigateToStartingActivity(this) Navigator.navigateToStartingActivity(this)
finish() finish()
} }
private fun loadPrivateKey(accounts: List<Account>, i: Int) {
if (i >= accounts.size) {
runOnUiThread { }
return
}
val alias = accounts[i].privateKeyAlias
if (alias != null && !CustomKeyManager.isCached(alias)) {
CustomKeyManager.cache(this, alias, object : CustomKeyManager.KeyCallback {
override fun onSuccess(entry: CustomKeyManager.KeyEntry) {
loadPrivateKey(accounts, i + 1)
}
override fun onError(e: Exception) {
loadPrivateKey(accounts, i + 1)
}
})
} else {
loadPrivateKey(accounts, i + 1)
}
}
} }
package com.commit451.gitlab.activity package com.commit451.gitlab.activity
   
import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.security.KeyChain
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputLayout import android.support.design.widget.TextInputLayout
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.util.Patterns
import android.view.View import android.view.View
import android.widget.EditText
import android.widget.TextView import android.widget.TextView
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import butterknife.OnClick import butterknife.OnClick
import butterknife.OnEditorAction import com.afollestad.materialdialogs.MaterialDialog
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.BuildConfig import com.commit451.gitlab.BuildConfig
import com.commit451.gitlab.R import com.commit451.gitlab.R
Loading
@@ -26,7 +22,6 @@ import com.commit451.gitlab.api.GitLab
Loading
@@ -26,7 +22,6 @@ import com.commit451.gitlab.api.GitLab
import com.commit451.gitlab.api.GitLabFactory import com.commit451.gitlab.api.GitLabFactory
import com.commit451.gitlab.api.MoshiProvider import com.commit451.gitlab.api.MoshiProvider
import com.commit451.gitlab.api.OkHttpClientFactory import com.commit451.gitlab.api.OkHttpClientFactory
import com.commit451.gitlab.api.request.SessionRequest
import com.commit451.gitlab.data.Prefs import com.commit451.gitlab.data.Prefs
import com.commit451.gitlab.dialog.HttpLoginDialog import com.commit451.gitlab.dialog.HttpLoginDialog
import com.commit451.gitlab.event.LoginEvent import com.commit451.gitlab.event.LoginEvent
Loading
@@ -40,9 +35,9 @@ import com.commit451.gitlab.model.api.User
Loading
@@ -40,9 +35,9 @@ import com.commit451.gitlab.model.api.User
import com.commit451.gitlab.navigation.Navigator import com.commit451.gitlab.navigation.Navigator
import com.commit451.gitlab.rx.CustomResponseSingleObserver import com.commit451.gitlab.rx.CustomResponseSingleObserver
import com.commit451.gitlab.ssl.CustomHostnameVerifier import com.commit451.gitlab.ssl.CustomHostnameVerifier
import com.commit451.gitlab.ssl.CustomKeyManager
import com.commit451.gitlab.ssl.X509CertificateException import com.commit451.gitlab.ssl.X509CertificateException
import com.commit451.gitlab.ssl.X509Util import com.commit451.gitlab.ssl.X509Util
import com.commit451.gitlab.util.IntentUtil
import com.commit451.teleprinter.Teleprinter import com.commit451.teleprinter.Teleprinter
import okhttp3.Credentials import okhttp3.Credentials
import okhttp3.HttpUrl import okhttp3.HttpUrl
Loading
@@ -65,8 +60,6 @@ class LoginActivity : BaseActivity() {
Loading
@@ -65,8 +60,6 @@ class LoginActivity : BaseActivity() {
   
private val EXTRA_SHOW_CLOSE = "show_close" private val EXTRA_SHOW_CLOSE = "show_close"
   
private val REQUEST_PRIVATE_TOKEN = 123
fun newIntent(context: Context, showClose: Boolean = false): Intent { fun newIntent(context: Context, showClose: Boolean = false): Intent {
val intent = Intent(context, LoginActivity::class.java) val intent = Intent(context, LoginActivity::class.java)
intent.putExtra(EXTRA_SHOW_CLOSE, showClose) intent.putExtra(EXTRA_SHOW_CLOSE, showClose)
Loading
@@ -77,32 +70,38 @@ class LoginActivity : BaseActivity() {
Loading
@@ -77,32 +70,38 @@ class LoginActivity : BaseActivity() {
@BindView(R.id.root) lateinit var root: View @BindView(R.id.root) lateinit var root: View
@BindView(R.id.toolbar) lateinit var toolbar: Toolbar @BindView(R.id.toolbar) lateinit var toolbar: Toolbar
@BindView(R.id.text_input_layout_server) lateinit var textInputLayoutUrl: TextInputLayout @BindView(R.id.text_input_layout_server) lateinit var textInputLayoutUrl: TextInputLayout
@BindView(R.id.user_input_hint) lateinit var textInputLayoutUser: TextInputLayout
@BindView(R.id.user_input) lateinit var textUser: EditText
@BindView(R.id.password_hint) lateinit var textInputLayoutPassword: TextInputLayout
@BindView(R.id.password_input) lateinit var textPassword: TextView
@BindView(R.id.token_hint) lateinit var textInputLayoutToken: TextInputLayout @BindView(R.id.token_hint) lateinit var textInputLayoutToken: TextInputLayout
@BindView(R.id.token_input) lateinit var textToken: TextView @BindView(R.id.token_input) lateinit var textToken: TextView
@BindView(R.id.normal_login) lateinit var rootNormalLogin: View
@BindView(R.id.token_login) lateinit var rootTokenLogin: View
@BindView(R.id.progress) lateinit var progress: View @BindView(R.id.progress) lateinit var progress: View
   
lateinit var teleprinter: Teleprinter lateinit var teleprinter: Teleprinter
   
var isNormalLogin = true
val emailPattern: Pattern by lazy {
Patterns.EMAIL_ADDRESS
}
val tokenPattern: Pattern by lazy { val tokenPattern: Pattern by lazy {
Pattern.compile("^[A-Za-z0-9-_]*$") Pattern.compile("^[A-Za-z0-9-_]*$")
} }
var account: Account = Account() var account: Account = Account()
var gitLab: GitLab? = null var gitLab: GitLab? = null
   
@OnEditorAction(R.id.password_input, R.id.token_input) @OnClick(R.id.button_info)
fun onPasswordEditorAction(): Boolean { fun onInfoClicked() {
onLoginClick() MaterialDialog.Builder(this)
return true .title(R.string.access_token_info_title)
.content(R.string.access_token_info_message)
.positiveText(R.string.create_personal_access_token)
.onPositive { _, _ ->
val validUrl = verifyUrl()
if (validUrl) {
val url = textInputLayoutUrl.text()
val accessTokenUrl = "$url/profile/personal_access_tokens"
IntentUtil.openPage(this, accessTokenUrl)
} else {
Snackbar.make(root, R.string.not_a_valid_url, Snackbar.LENGTH_SHORT)
.show()
}
}
.negativeText(R.string.cancel)
.show()
} }
   
@OnClick(R.id.login_button) @OnClick(R.id.login_button)
Loading
@@ -118,24 +117,18 @@ class LoginActivity : BaseActivity() {
Loading
@@ -118,24 +117,18 @@ class LoginActivity : BaseActivity() {
} }
val uri = textInputLayoutUrl.text() val uri = textInputLayoutUrl.text()
   
if (isNormalLogin) { if (!textInputLayoutToken.checkValid()) {
val valid = textInputLayoutUser.checkValid() and textInputLayoutPassword.checkValid() return
if (!valid) { }
return if (!tokenPattern.matcher(textToken.text).matches()) {
} textInputLayoutToken.error = getString(R.string.not_a_valid_private_token)
return
} else { } else {
if (!textInputLayoutToken.checkValid()) { textInputLayoutToken.error = null
return
}
if (!tokenPattern.matcher(textToken.text).matches()) {
textInputLayoutToken.error = getString(R.string.not_a_valid_private_token)
return
} else {
textInputLayoutToken.error = null
}
} }
   
if (isAlreadySignedIn(uri.toString(), if (isNormalLogin) textUser.text.toString() else textToken.text.toString())) {
if (isAlreadySignedIn(uri, textToken.text.toString())) {
Snackbar.make(root, getString(R.string.already_logged_in), Snackbar.LENGTH_LONG) Snackbar.make(root, getString(R.string.already_logged_in), Snackbar.LENGTH_LONG)
.show() .show()
return return
Loading
@@ -147,22 +140,6 @@ class LoginActivity : BaseActivity() {
Loading
@@ -147,22 +140,6 @@ class LoginActivity : BaseActivity() {
login() login()
} }
   
@OnClick(R.id.button_open_login_page)
fun onOpenLoginPageClicked() {
if (verifyUrl()) {
val url = textInputLayoutUrl.editText!!.text.toString()
Navigator.navigateToWebSignin(this, url, true, REQUEST_PRIVATE_TOKEN)
}
}
@OnClick(R.id.button_open_login_page_for_personal_access)
fun onOpenLoginPageForPersonalAccessTokenClicked() {
if (verifyUrl()) {
val url = textInputLayoutUrl.editText!!.text.toString()
Navigator.navigateToWebSignin(this, url, false, REQUEST_PRIVATE_TOKEN)
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login) setContentView(R.layout.activity_login)
Loading
@@ -171,27 +148,6 @@ class LoginActivity : BaseActivity() {
Loading
@@ -171,27 +148,6 @@ class LoginActivity : BaseActivity() {
teleprinter = Teleprinter(this) teleprinter = Teleprinter(this)
val showClose = intent.getBooleanExtra(EXTRA_SHOW_CLOSE, false) val showClose = intent.getBooleanExtra(EXTRA_SHOW_CLOSE, false)
   
toolbar.inflateMenu(R.menu.advanced_login)
toolbar.setOnMenuItemClickListener(Toolbar.OnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_advanced_login -> {
val isNormalLogin = rootNormalLogin.visibility == View.VISIBLE
if (isNormalLogin) {
rootNormalLogin.visibility = View.GONE
rootTokenLogin.visibility = View.VISIBLE
item.setTitle(R.string.normal_link)
this@LoginActivity.isNormalLogin = false
} else {
rootNormalLogin.visibility = View.VISIBLE
rootTokenLogin.visibility = View.GONE
item.setTitle(R.string.advanced_login)
this@LoginActivity.isNormalLogin = true
}
return@OnMenuItemClickListener true
}
}
false
})
if (showClose) { if (showClose) {
toolbar.setNavigationIcon(R.drawable.ic_close_24dp) toolbar.setNavigationIcon(R.drawable.ic_close_24dp)
toolbar.setNavigationOnClickListener { onBackPressed() } toolbar.setNavigationOnClickListener { onBackPressed() }
Loading
@@ -200,69 +156,15 @@ class LoginActivity : BaseActivity() {
Loading
@@ -200,69 +156,15 @@ class LoginActivity : BaseActivity() {
textInputLayoutUrl.editText?.setText(R.string.url_gitlab) textInputLayoutUrl.editText?.setText(R.string.url_gitlab)
} }
   
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun hasBrowsableLinks(): Boolean {
super.onActivityResult(requestCode, resultCode, data) return true
when (requestCode) {
REQUEST_PRIVATE_TOKEN -> if (resultCode == Activity.RESULT_OK) {
val token = data?.getStringExtra(WebLoginActivity.EXTRA_TOKEN)
textInputLayoutToken.editText!!.setText(token)
}
}
} }
   
fun connect(byAuth: Boolean) { fun connect() {
progress.visibility = View.VISIBLE progress.visibility = View.VISIBLE
progress.alpha = 0.0f progress.alpha = 0.0f
progress.animate().alpha(1.0f) progress.animate().alpha(1.0f)
   
if (byAuth) {
connectByAuth()
} else {
connectByToken()
}
}
fun connectByAuth() {
val request = SessionRequest()
request.password = textInputLayoutPassword.text()
val usernameOrEmail = textInputLayoutUser.text()
if (emailPattern.matcher(usernameOrEmail).matches()) {
request.email = usernameOrEmail
} else {
request.login = usernameOrEmail
}
attemptLogin(request)
}
fun attemptLogin(request: SessionRequest) {
val clientBuilder = OkHttpClientFactory.create(account)
if (BuildConfig.DEBUG) {
clientBuilder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
}
gitLab = GitLabFactory.createGitLab(account, clientBuilder)
gitLab!!.login(request)
.setup(bindToLifecycle())
.subscribe(object : CustomResponseSingleObserver<User>() {
override fun error(e: Throwable) {
Timber.e(e)
if (e is HttpException) {
handleConnectionResponse(response())
} else {
handleConnectionError(e)
}
}
override fun responseNonNullSuccess(userLogin: User) {
account.privateToken = userLogin.privateToken
loadUser(clientBuilder)
}
})
}
fun connectByToken() {
account.privateToken = textToken.text.toString() account.privateToken = textToken.text.toString()
val gitlabClientBuilder = OkHttpClientFactory.create(account, false) val gitlabClientBuilder = OkHttpClientFactory.create(account, false)
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Loading
@@ -274,30 +176,6 @@ class LoginActivity : BaseActivity() {
Loading
@@ -274,30 +176,6 @@ class LoginActivity : BaseActivity() {
loadUser(gitlabClientBuilder) loadUser(gitlabClientBuilder)
} }
   
fun loginWithPrivateToken() {
val serverUri = Uri.parse(account.serverUrl)
KeyChain.choosePrivateKeyAlias(this, { alias ->
account.privateKeyAlias = alias
if (alias != null) {
if (!CustomKeyManager.isCached(alias)) {
CustomKeyManager.cache(this@LoginActivity, alias, object : CustomKeyManager.KeyCallback {
override fun onSuccess(entry: CustomKeyManager.KeyEntry) {
runOnUiThread { login() }
}
override fun onError(e: Exception) {
account.privateKeyAlias = null
Timber.e(e, "Failed to load private key")
}
})
} else {
runOnUiThread { login() }
}
}
}, null, null, serverUri.host, serverUri.port, null)
}
fun verifyUrl(): Boolean { fun verifyUrl(): Boolean {
val url = textInputLayoutUrl.text() val url = textInputLayoutUrl.text()
var uri: Uri? = null var uri: Uri? = null
Loading
@@ -316,8 +194,7 @@ class LoginActivity : BaseActivity() {
Loading
@@ -316,8 +194,7 @@ class LoginActivity : BaseActivity() {
textInputLayoutUrl.error = null textInputLayoutUrl.error = null
} }
if (!url.endsWith("/")) { if (!url.endsWith("/")) {
textInputLayoutUrl.error = getString(R.string.please_end_your_url_with_a_slash) textInputLayoutUrl.editText?.setText(url + "/")
return false
} else { } else {
textInputLayoutUrl.error = null textInputLayoutUrl.error = null
} }
Loading
@@ -327,20 +204,14 @@ class LoginActivity : BaseActivity() {
Loading
@@ -327,20 +204,14 @@ class LoginActivity : BaseActivity() {
fun login() { fun login() {
// This seems useless - But believe me, it makes everything work! Don't remove it. // This seems useless - But believe me, it makes everything work! Don't remove it.
// (OkHttpClientFactory caches the clients and needs a new account to recreate them) // (OkHttpClientFactory caches the clients and needs a new account to recreate them)
val newAccount = Account() val newAccount = Account()
newAccount.serverUrl = account.serverUrl newAccount.serverUrl = account.serverUrl
newAccount.trustedCertificate = account.trustedCertificate newAccount.trustedCertificate = account.trustedCertificate
newAccount.trustedHostname = account.trustedHostname newAccount.trustedHostname = account.trustedHostname
newAccount.privateKeyAlias = account.privateKeyAlias
newAccount.authorizationHeader = account.authorizationHeader newAccount.authorizationHeader = account.authorizationHeader
account = newAccount account = newAccount
   
if (isNormalLogin) { connect()
connect(true)
} else {
connect(false)
}
} }
   
fun loadUser(gitlabClientBuilder: OkHttpClient.Builder) { fun loadUser(gitlabClientBuilder: OkHttpClient.Builder) {
Loading
@@ -364,8 +235,9 @@ class LoginActivity : BaseActivity() {
Loading
@@ -364,8 +235,9 @@ class LoginActivity : BaseActivity() {
   
override fun responseNonNullSuccess(userFull: User) { override fun responseNonNullSuccess(userFull: User) {
progress.visibility = View.GONE progress.visibility = View.GONE
account.user = userFull
account.lastUsed = Date() account.lastUsed = Date()
account.email = userFull.email
account.username = userFull.username
Prefs.addAccount(account) Prefs.addAccount(account)
App.get().setAccount(account) App.get().setAccount(account)
App.bus().post(LoginEvent(account)) App.bus().post(LoginEvent(account))
Loading
@@ -492,9 +364,7 @@ class LoginActivity : BaseActivity() {
Loading
@@ -492,9 +364,7 @@ class LoginActivity : BaseActivity() {
fun isAlreadySignedIn(url: String, usernameOrEmailOrPrivateToken: String): Boolean { fun isAlreadySignedIn(url: String, usernameOrEmailOrPrivateToken: String): Boolean {
val accounts = Prefs.getAccounts() val accounts = Prefs.getAccounts()
return accounts.any { return accounts.any {
it.serverUrl == url && (usernameOrEmailOrPrivateToken == it.user?.username it.serverUrl == url && usernameOrEmailOrPrivateToken == it.privateToken
|| usernameOrEmailOrPrivateToken.equals(it.user?.email, ignoreCase = true)
|| usernameOrEmailOrPrivateToken.equals(it.privateToken, ignoreCase = true))
} }
} }
} }
Loading
@@ -20,7 +20,7 @@ import com.commit451.addendum.parceler.getParcelerParcelable
Loading
@@ -20,7 +20,7 @@ import com.commit451.addendum.parceler.getParcelerParcelable
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelable import com.commit451.addendum.parceler.putParcelerParcelable
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.alakazam.HideRunnable import com.commit451.alakazam.fadeOut
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
import com.commit451.gitlab.adapter.ProjectPagerAdapter import com.commit451.gitlab.adapter.ProjectPagerAdapter
Loading
@@ -196,17 +196,13 @@ class ProjectActivity : BaseActivity() {
Loading
@@ -196,17 +196,13 @@ class ProjectActivity : BaseActivity() {
   
override fun error(t: Throwable) { override fun error(t: Throwable) {
Timber.e(t) Timber.e(t)
progress.animate() progress.fadeOut()
.alpha(0.0f)
.withEndAction(HideRunnable(progress))
Snackbar.make(root, getString(R.string.connection_error), Snackbar.LENGTH_SHORT) Snackbar.make(root, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show() .show()
} }
   
override fun success(project: Project) { override fun success(project: Project) {
progress.animate() progress.fadeOut()
.alpha(0.0f)
.withEndAction(HideRunnable(progress))
bindProject(project) bindProject(project)
} }
}) })
Loading
Loading
Loading
@@ -15,8 +15,9 @@ import butterknife.BindView
Loading
@@ -15,8 +15,9 @@ import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import com.commit451.addendum.parceler.getParcelerParcelableExtra import com.commit451.addendum.parceler.getParcelerParcelableExtra
import com.commit451.addendum.parceler.putParcelerParcelableExtra import com.commit451.addendum.parceler.putParcelerParcelableExtra
import com.commit451.alakazam.Alakazam import com.commit451.addendum.themeAttrColor
import com.commit451.easel.Easel import com.commit451.alakazam.navigationBarColorAnimator
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
import com.commit451.gitlab.extension.feedUrl import com.commit451.gitlab.extension.feedUrl
Loading
@@ -91,23 +92,23 @@ class UserActivity : BaseActivity() {
Loading
@@ -91,23 +92,23 @@ class UserActivity : BaseActivity() {
   
fun bindPalette(palette: Palette) { fun bindPalette(palette: Palette) {
val animationTime = 1000 val animationTime = 1000
val vibrantColor = palette.getVibrantColor(Easel.getThemeAttrColor(this, R.attr.colorPrimary)) val vibrantColor = palette.getVibrantColor(this.themeAttrColor(R.attr.colorPrimary))
val darkerColor = Easel.getDarkerColor(vibrantColor) val darkerColor = this.themeAttrColor(vibrantColor)
   
if (Build.VERSION.SDK_INT >= 21) { if (Build.VERSION.SDK_INT >= 21) {
Alakazam.navigationBarColorAnimator(window, darkerColor) window.navigationBarColorAnimator(darkerColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
window.statusBarColor = darkerColor window.statusBarColor = darkerColor
} }
   
ObjectAnimator.ofObject(collapsingToolbarLayout, "contentScrimColor", ArgbEvaluator(), ObjectAnimator.ofObject(collapsingToolbarLayout, "contentScrimColor", ArgbEvaluator(),
Easel.getThemeAttrColor(this, R.attr.colorPrimary), vibrantColor) this.themeAttrColor(R.attr.colorPrimary), vibrantColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
   
ObjectAnimator.ofObject(collapsingToolbarLayout, "statusBarScrimColor", ArgbEvaluator(), ObjectAnimator.ofObject(collapsingToolbarLayout, "statusBarScrimColor", ArgbEvaluator(),
Easel.getThemeAttrColor(this, R.attr.colorPrimaryDark), darkerColor) this.themeAttrColor(R.attr.colorPrimaryDark), darkerColor)
.setDuration(animationTime.toLong()) .setDuration(animationTime.toLong())
.start() .start()
   
Loading
Loading
package com.commit451.gitlab.activity
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.support.annotation.Keep
import android.support.v7.widget.Toolbar
import android.view.View
import android.webkit.*
import butterknife.BindView
import butterknife.ButterKnife
import com.commit451.gitlab.R
import me.zhanghai.android.materialprogressbar.MaterialProgressBar
/**
* Shows user a WebView for login and intercepts the headers to get the private token. Hmmmm
*/
class WebLoginActivity : BaseActivity() {
companion object {
val EXTRA_TOKEN = "token"
private val JAVASCRIPT_INTERFACE_EXTRACTOR = "TokenExtractor"
/**
* This is pretty fragile and has changed in the past, so if this screen ever stops working,
* it's probably due to this id changing. Go inspect the source of the page to verify
*/
private val PRIVATE_TOKEN_HTML_ID = "private-token"
private val KEY_URL = "url"
private val KEY_EXTRACTING_PRIVATE_TOKEN = "extracting_private_token"
fun newIntent(context: Context, url: String, extractingPrivateToken: Boolean): Intent {
val intent = Intent(context, WebLoginActivity::class.java)
intent.putExtra(KEY_URL, url)
intent.putExtra(KEY_EXTRACTING_PRIVATE_TOKEN, extractingPrivateToken)
return intent
}
}
@BindView(R.id.toolbar) lateinit var toolbar: Toolbar
@BindView(R.id.progress) lateinit var progress: MaterialProgressBar
@BindView(R.id.webview) lateinit var webView: WebView
lateinit var url: String
val isExtracting: Boolean by lazy {
intent.getBooleanExtra(KEY_EXTRACTING_PRIVATE_TOKEN, false)
}
val webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView, newProgress: Int) {
super.onProgressChanged(view, newProgress)
if (progress.visibility != View.VISIBLE) {
progress.visibility = View.VISIBLE
}
progress.progress = newProgress
if (newProgress == 100) {
progress.visibility = View.GONE
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_webview_login)
ButterKnife.bind(this)
url = intent.getStringExtra(KEY_URL)
if (url.endsWith("/")) {
url = url.substring(0, url.length - 1)
}
toolbar.setNavigationIcon(R.drawable.ic_back_24dp)
toolbar.setNavigationOnClickListener { onBackPressed() }
val settings = webView.settings
settings.javaScriptEnabled = true
webView.addJavascriptInterface(HtmlExtractorJavaScriptInterface(), JAVASCRIPT_INTERFACE_EXTRACTOR)
webView.setWebViewClient(ExtractionWebClient())
webView.setWebChromeClient(webChromeClient)
webView.clearCache(true)
webView.clearFormData()
webView.clearHistory()
clearCookies()
webView.loadUrl(url + "/users/sign_in")
}
@Suppress("DEPRECATION")
fun clearCookies() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
CookieManager.getInstance().removeAllCookies(null)
CookieManager.getInstance().flush()
} else {
val cookieSyncManager = CookieSyncManager.createInstance(this)
cookieSyncManager.startSync()
val cookieManager = CookieManager.getInstance()
cookieManager.removeAllCookie()
cookieManager.removeSessionCookie()
cookieSyncManager.stopSync()
cookieSyncManager.sync()
}
}
inner class ExtractionWebClient : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
var modifiedUrl = url
if (modifiedUrl.endsWith("/")) {
modifiedUrl = url.substring(0, url.length - 1)
}
if (modifiedUrl == this@WebLoginActivity.url) {
if (isExtracting) {
webView.loadUrl(this@WebLoginActivity.url + "/profile/account")
} else {
webView.loadUrl(this@WebLoginActivity.url + "/profile/personal_access_tokens")
}
return
}
if (modifiedUrl == this@WebLoginActivity.url + "/profile/account") {
webView.loadUrl("javascript:" + JAVASCRIPT_INTERFACE_EXTRACTOR + ".extract" +
"(document.getElementById('" + PRIVATE_TOKEN_HTML_ID + "').value);")
return
}
super.onPageFinished(view, url)
}
}
inner class HtmlExtractorJavaScriptInterface {
@JavascriptInterface
@Keep
fun extract(token: String) {
val data = Intent()
data.putExtra(EXTRA_TOKEN, token)
setResult(Activity.RESULT_OK, data)
finish()
}
}
}
Loading
@@ -4,6 +4,7 @@ import android.content.Context
Loading
@@ -4,6 +4,7 @@ import android.content.Context
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.PopupMenu import android.widget.PopupMenu
import com.commit451.addendum.themeAttrColor
import com.commit451.easel.Easel import com.commit451.easel.Easel
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.R import com.commit451.gitlab.R
Loading
@@ -24,7 +25,7 @@ class AccountAdapter(context: Context, private val listener: AccountAdapter.List
Loading
@@ -24,7 +25,7 @@ class AccountAdapter(context: Context, private val listener: AccountAdapter.List
} }
   
private val accounts = mutableListOf<Account>() private val accounts = mutableListOf<Account>()
private val colorControlHighlight: Int = Easel.getThemeAttrColor(context, R.attr.colorControlHighlight) private val colorControlHighlight: Int = context.themeAttrColor(R.attr.colorControlHighlight)
   
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) { when (viewType) {
Loading
Loading
Loading
@@ -12,9 +12,8 @@ import java.io.IOException
Loading
@@ -12,9 +12,8 @@ import java.io.IOException
class AuthenticationRequestInterceptor(private val account: Account) : Interceptor { class AuthenticationRequestInterceptor(private val account: Account) : Interceptor {
   
companion object { companion object {
val AUTHORIZATION_HEADER_FIELD = "Authorization" const val PRIVATE_TOKEN_HEADER_FIELD = "Private-Token"
val PRIVATE_TOKEN_HEADER_FIELD = "PRIVATE-TOKEN" private const val PRIVATE_TOKEN_GET_PARAMETER = "private_token"
val PRIVATE_TOKEN_GET_PARAMETER = "private_token"
} }
   
@Throws(IOException::class) @Throws(IOException::class)
Loading
@@ -30,13 +29,6 @@ class AuthenticationRequestInterceptor(private val account: Account) : Intercept
Loading
@@ -30,13 +29,6 @@ class AuthenticationRequestInterceptor(private val account: Account) : Intercept
cleanServerUrl = cleanServerUrl.substring(cleanServerUrl.indexOf(':')) cleanServerUrl = cleanServerUrl.substring(cleanServerUrl.indexOf(':'))
   
if (cleanUrl.startsWith(cleanServerUrl)) { if (cleanUrl.startsWith(cleanServerUrl)) {
val authorizationHeader = account.authorizationHeader
if (authorizationHeader != null) {
request = request.newBuilder()
.header(AUTHORIZATION_HEADER_FIELD, authorizationHeader)
.build()
}
val privateToken = account.privateToken val privateToken = account.privateToken
if (privateToken == null) { if (privateToken == null) {
Timber.e("The private token was null") Timber.e("The private token was null")
Loading
Loading
package com.commit451.gitlab.api package com.commit451.gitlab.api
   
import com.commit451.gitlab.api.request.SessionRequest
import com.commit451.gitlab.api.response.FileUploadResponse import com.commit451.gitlab.api.response.FileUploadResponse
import com.commit451.gitlab.model.api.* import com.commit451.gitlab.model.api.*
import io.reactivex.Completable import io.reactivex.Completable
Loading
@@ -21,11 +20,6 @@ interface GitLabService {
Loading
@@ -21,11 +20,6 @@ interface GitLabService {
const val MAX_TREE_PER_PAGE = "100" const val MAX_TREE_PER_PAGE = "100"
} }
   
/* --- LOGIN --- */
@POST(API_VERSION + "/session")
fun login(@Body request: SessionRequest): Single<Response<User>>
/* --- USERS --- */ /* --- USERS --- */
   
/** /**
Loading
Loading
Loading
@@ -22,9 +22,12 @@ object OkHttpClientFactory {
Loading
@@ -22,9 +22,12 @@ object OkHttpClientFactory {
fun create(account: Account, includeSignInAuthenticator: Boolean = true): OkHttpClient.Builder { fun create(account: Account, includeSignInAuthenticator: Boolean = true): OkHttpClient.Builder {
// A custom trust manager, otherwise SSL won't work properly with some configurations // A custom trust manager, otherwise SSL won't work properly with some configurations
val customTrustManager = CustomTrustManager() val customTrustManager = CustomTrustManager()
customTrustManager.setTrustedCertificate(account.trustedCertificate) account.trustedCertificate?.let {
customTrustManager.setTrustedHostname(account.trustedHostname) customTrustManager.setTrustedCertificate(it)
customTrustManager.setPrivateKeyAlias(account.privateKeyAlias) }
account.trustedHostname?.let {
customTrustManager.setTrustedHostname(it)
}
   
val builder = OkHttpClient.Builder() val builder = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
Loading
Loading
package com.commit451.gitlab.api.request
import com.squareup.moshi.Json
/**
* Start a session
*/
class SessionRequest {
@field:Json(name = "email")
var email: String? = null
@field:Json(name = "login")
var login: String? = null
@field:Json(name = "password")
var password: String? = null
}
Loading
@@ -21,9 +21,9 @@ import timber.log.Timber
Loading
@@ -21,9 +21,9 @@ import timber.log.Timber
*/ */
object Prefs { object Prefs {
   
val KEY_ACCOUNTS = "accounts" private const val KEY_ACCOUNTS = "accounts"
val KEY_STARTING_VIEW = "starting_view" private const val KEY_STARTING_VIEW = "starting_view"
val KEY_REQUIRE_DEVICE_AUTH = "require_device_auth" private const val KEY_REQUIRE_DEVICE_AUTH = "require_device_auth"
   
const val STARTING_VIEW_PROJECTS = 0 const val STARTING_VIEW_PROJECTS = 0
const val STARTING_VIEW_GROUPS = 1 const val STARTING_VIEW_GROUPS = 1
Loading
Loading
Loading
@@ -5,6 +5,7 @@ import android.os.Bundle
Loading
@@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.View import android.view.View
   
import com.commit451.gitlab.App import com.commit451.gitlab.App
import com.commit451.gitlab.activity.BaseActivity
import com.commit451.gitlab.event.ReloadDataEvent import com.commit451.gitlab.event.ReloadDataEvent
import com.trello.rxlifecycle2.components.support.RxFragment import com.trello.rxlifecycle2.components.support.RxFragment
   
Loading
@@ -13,9 +14,12 @@ import org.greenrobot.eventbus.Subscribe
Loading
@@ -13,9 +14,12 @@ import org.greenrobot.eventbus.Subscribe
   
open class BaseFragment : RxFragment() { open class BaseFragment : RxFragment() {
   
var baseEventReceiver: EventReceiver? = null private var baseEventReceiver: EventReceiver? = null
val baseActivty by lazy {
activity as BaseActivity
}
   
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
   
baseEventReceiver = EventReceiver() baseEventReceiver = EventReceiver()
Loading
Loading