From f610d72cd1eae3cd0047493408bb31f9bb6be772 Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Fri, 19 May 2017 11:13:02 -0400 Subject: [PATCH 1/6] Remove "Gists" Section. Previously, the section where "Actions" were, was titled "Gists" for some reason. This fixes that. --- app/build.gradle | 14 ++----- .../com/fastaccess/ui/base/AdActivity.java | 2 - app/src/main/res/menu/drawer_menu.xml | 39 ++++++++----------- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f9bcdb02..ee1599bb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,11 +25,11 @@ android { } } compileSdkVersion 25 - buildToolsVersion "26-rc1" + buildToolsVersion "26.0.0-rc1" defaultConfig { applicationId "com.fastaccess.github" minSdkVersion 21 - targetSdkVersion 26 + targetSdkVersion 25 versionCode 210 versionName "2.1.0" signingConfig signingConfigs.signing @@ -107,12 +107,6 @@ android { testOptions { unitTests.returnDefaultValues = true } - - splits{ - density{ - enable true - } - } } repositories { @@ -143,11 +137,11 @@ dependencies { compile "com.jakewharton:butterknife:${butterKnifeVersion}" compile 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:2.0.1-rc1' compile 'io.reactivex:rxandroid:1.2.1' - compile 'io.reactivex:rxjava:1.2.2' + compile 'io.reactivex:rxjava:1.2.3' compile 'com.squareup.okhttp3:logging-interceptor:3.3.1' compile 'com.annimon:stream:1.1.7' compile 'com.github.GrenderG:Toasty:1.1.3' - compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2' + compile 'com.github.JediBurrell:MaterialTapTargetPrompt:-SNAPSHOT' compile 'com.github.k0shk0sh:RetainedDateTimePickers:1.0.2' compile 'com.github.daniel-stoneuk:material-about-library:1.8.1' compile 'io.requery:requery:1.3.0' diff --git a/app/src/fdroid/java/com/fastaccess/ui/base/AdActivity.java b/app/src/fdroid/java/com/fastaccess/ui/base/AdActivity.java index 5fe3487d..59125b52 100644 --- a/app/src/fdroid/java/com/fastaccess/ui/base/AdActivity.java +++ b/app/src/fdroid/java/com/fastaccess/ui/base/AdActivity.java @@ -1,11 +1,9 @@ package com.fastaccess.ui.base; import android.support.annotation.Nullable; -import android.view.View; import android.widget.TextView; import com.fastaccess.R; -import com.fastaccess.helper.PrefGetter; import net.grandcentrix.thirtyinch.TiActivity; import net.grandcentrix.thirtyinch.TiPresenter; diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml index 4e5ee647..d39ffcf0 100644 --- a/app/src/main/res/menu/drawer_menu.xml +++ b/app/src/main/res/menu/drawer_menu.xml @@ -47,27 +47,22 @@ - - - - - - - - - - + + + + + \ No newline at end of file From 8c7390f5596c3461f3b3ee6e199f4efbf6540d28 Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Fri, 19 May 2017 13:54:29 -0400 Subject: [PATCH 2/6] Support Android O Autofill. FastHub will now support Autofill by Google ( and probably other autofill providers ), in Android O. --- app/build.gradle | 4 +- .../ui/modules/login/LoginActivity.java | 9 +- .../layout-v26/login_form_layout.xml | 170 ++++++++++++++++++ .../main_layouts/layout/login_form_layout.xml | 1 + 4 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml diff --git a/app/build.gradle b/app/build.gradle index ee1599bb..8d9c8c18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,12 +24,12 @@ android { storePassword((buildProperties.secrets['android_store_password'] | buildProperties.notThere['android_store_password']).string) } } - compileSdkVersion 25 + compileSdkVersion 'android-O' buildToolsVersion "26.0.0-rc1" defaultConfig { applicationId "com.fastaccess.github" minSdkVersion 21 - targetSdkVersion 25 + targetSdkVersion 'O' versionCode 210 versionName "2.1.0" signingConfig signingConfigs.signing diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java index 8d627903..70a8e0bf 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -150,7 +151,13 @@ public class LoginActivity extends BaseActivity i isBasicAuth = getIntent().getExtras().getBoolean(BundleConstant.YES_NO_EXTRA); } } - if (password != null) password.setHint(isBasicAuth ? getString(R.string.password) : getString(R.string.access_token)); + if (username != null) + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + username.setAutofillHints(View.AUTOFILL_HINT_USERNAME); + if (password != null) { + password.setHint(isBasicAuth ? getString(R.string.password) : getString(R.string.access_token)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD); + } if (Arrays.asList(getResources().getStringArray(R.array.languages_array_values)).contains(Locale.getDefault().getLanguage())){ String language = PrefHelper.getString("app_language"); PrefHelper.set("app_language", Locale.getDefault().getLanguage()); diff --git a/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml b/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml new file mode 100644 index 00000000..adc072eb --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml index bb724de0..76d89c0c 100644 --- a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml @@ -70,6 +70,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" + android:autoFillMode="auto" android:maxLines="1"/> From f490acb1b137e461504ec2604a469622c03494f9 Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Sat, 20 May 2017 00:52:24 -0400 Subject: [PATCH 3/6] Fix Sudden AutoFill errors. Decided to randomly start causing errors, fixed. --- .../res/layouts/main_layouts/layout-v26/login_form_layout.xml | 2 -- .../main/res/layouts/main_layouts/layout/login_form_layout.xml | 1 - 2 files changed, 3 deletions(-) diff --git a/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml b/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml index adc072eb..bb724de0 100644 --- a/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout-v26/login_form_layout.xml @@ -69,7 +69,6 @@ android:id="@+id/usernameEditText" android:layout_width="match_parent" android:layout_height="wrap_content" - android:autoFillMode="auto" android:inputType="text" android:maxLines="1"/> @@ -89,7 +88,6 @@ android:layout_height="wrap_content" android:imeOptions="actionSend" android:inputType="textPassword" - android:autoFillMode="auto" android:maxLines="1"/> diff --git a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml index 76d89c0c..bb724de0 100644 --- a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml @@ -70,7 +70,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" - android:autoFillMode="auto" android:maxLines="1"/> From 7dc4b2b4b78e3fa97356d89fdf14eca66db7a34f Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Sat, 20 May 2017 00:53:33 -0400 Subject: [PATCH 4/6] Add Google Smart Lock. You now no longer have to type in your email and password, with Google Smart Lock. Simply tap "Basic Authentication", and if you've previously logged in, let Google do it's magic and you don't even touch that log-in form. --- app/build.gradle | 3 +- app/src/main/java/com/fastaccess/App.java | 12 +++ .../com/fastaccess/ui/base/BaseActivity.java | 10 +- .../ui/modules/login/LoginActivity.java | 96 ++++++++++++++++++- .../fastaccess/ui/modules/login/LoginMvp.java | 4 +- .../ui/modules/login/LoginPresenter.java | 13 ++- 6 files changed, 125 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8d9c8c18..af4a99a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,7 +25,7 @@ android { } } compileSdkVersion 'android-O' - buildToolsVersion "26.0.0-rc1" + buildToolsVersion "26.0.0-rc2" defaultConfig { applicationId "com.fastaccess.github" minSdkVersion 21 @@ -162,6 +162,7 @@ dependencies { compile "com.google.firebase:firebase-messaging:${firebase}" releaseCompile "com.google.firebase:firebase-crash:${firebase}" } + compile "com.google.android.gms:play-services-auth:10.2.6" testCompile "junit:junit:${junitVersion}" testCompile "org.mockito:mockito-core:${mockitoVersion}" testCompile "org.assertj:assertj-core:${assertjVersion}" diff --git a/app/src/main/java/com/fastaccess/App.java b/app/src/main/java/com/fastaccess/App.java index a8eec359..65b20c2f 100644 --- a/app/src/main/java/com/fastaccess/App.java +++ b/app/src/main/java/com/fastaccess/App.java @@ -8,6 +8,9 @@ import com.fastaccess.data.dao.model.Models; import com.fastaccess.helper.TypeFaceHelper; import com.fastaccess.provider.tasks.notification.NotificationSchedulerJobTask; import com.fastaccess.provider.uil.UILProvider; +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.common.Scopes; +import com.google.android.gms.common.api.GoogleApiClient; import io.requery.Persistable; import io.requery.android.sqlite.DatabaseSource; @@ -27,6 +30,7 @@ import shortbread.Shortbread; public class App extends Application { private static App instance; private SingleEntityStore dataStore; + private static GoogleApiClient googleApiClient; @Override public void onCreate() { super.onCreate(); @@ -46,6 +50,10 @@ public class App extends Application { TypeFaceHelper.generateTypeface(this); NotificationSchedulerJobTask.scheduleJob(this); Shortbread.create(this); + googleApiClient = new GoogleApiClient.Builder(this) + .addApi(Auth.CREDENTIALS_API) + .build(); + googleApiClient.connect(); } public SingleEntityStore getDataStore() { @@ -60,4 +68,8 @@ public class App extends Application { } return dataStore; } + + public GoogleApiClient getGoogleApiClient() { + return googleApiClient; + } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java index bc7bd07c..cf6f8893 100644 --- a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java +++ b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java @@ -32,6 +32,7 @@ import com.fastaccess.helper.BundleConstant; import com.fastaccess.helper.Bundler; import com.fastaccess.helper.InputHelper; import com.fastaccess.helper.PrefGetter; +import com.fastaccess.helper.PrefHelper; import com.fastaccess.helper.ViewHelper; import com.fastaccess.ui.base.mvp.BaseMvp; import com.fastaccess.ui.base.mvp.presenter.BasePresenter; @@ -50,6 +51,7 @@ import com.fastaccess.ui.modules.user.UserPagerActivity; import com.fastaccess.ui.widgets.AvatarLayout; import com.fastaccess.ui.widgets.dialog.MessageDialogView; import com.fastaccess.ui.widgets.dialog.ProgressDialogFragment; +import com.google.android.gms.auth.api.Auth; import com.nostra13.universalimageloader.core.ImageLoader; import java.util.ArrayList; @@ -139,7 +141,11 @@ public abstract class BaseActivity i @Nullable @BindView(R.id.login) FloatingActionButton login; @Nullable @BindView(R.id.progress) ProgressBar progress; + private String pass; + private static int RESOLUTION_CODE = 100; + private static int RESOLUTION_CHOOSER_CODE = 101; + @State boolean isBasicAuth; public static void start(@NonNull Activity activity, boolean isBasicAuth) { @@ -65,6 +75,7 @@ public class LoginActivity extends BaseActivity i .put(BundleConstant.YES_NO_EXTRA, isBasicAuth) .end()); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("smartLock", true); activity.startActivity(intent); activity.finish(); } @@ -138,11 +149,43 @@ public class LoginActivity extends BaseActivity i hideProgress(); Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(SlackBottomSheetDialog.TAG, true); startActivity(intent); finishAffinity(); } + @Override public void onSuccessfullyLoggedIn(Login userModel) { + Credential credential = new Credential.Builder(userModel.getLogin()) + .setPassword(pass) + .setProfilePictureUri(Uri.parse(userModel.getAvatarUrl())) + .build(); + Auth.CredentialsApi.save(App.getInstance().getGoogleApiClient(), credential).setResultCallback(status -> { + if(status.isSuccess()) { + onSuccessfullyLoggedIn(); + } else if(status.hasResolution()){ + try { + status.startResolutionForResult(this, RESOLUTION_CODE); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + } else { + Log.e(getLoggingTag(), status+""); + onSuccessfullyLoggedIn(); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode==RESOLUTION_CODE) { + onSuccessfullyLoggedIn(); + } else if (requestCode==RESOLUTION_CHOOSER_CODE) { + if (resultCode==RESULT_OK) { + Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); + doLogin(credential.getId(), credential.getPassword()); + } + } + } + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.LoginTheme); super.onCreate(savedInstanceState); @@ -166,6 +209,43 @@ public class LoginActivity extends BaseActivity i if(!Locale.getDefault().getLanguage().equals(language)) recreate(); } + + if(isBasicAuth&&getIntent()!=null) + if(getIntent().hasExtra("smartLock")) + if(App.getInstance().getGoogleApiClient().isConnecting()&& + !App.getInstance().getGoogleApiClient().isConnected()) { + App.getInstance().getGoogleApiClient().registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { + @Override + public void onConnected(@Nullable Bundle bundle) { + doCredentialRequest(); + } + @Override + public void onConnectionSuspended(int i) { + } + }); + } else { + doCredentialRequest(); + } + } + + private void doCredentialRequest() { + CredentialRequest credentialRequest = new CredentialRequest.Builder() + .setPasswordLoginSupported(true) + .build(); + Auth.CredentialsApi.request(App.getInstance().getGoogleApiClient(), credentialRequest).setResultCallback(credentialRequestResult -> { + if(credentialRequestResult.getStatus().isSuccess()) { + doLogin(credentialRequestResult.getCredential().getId(), + credentialRequestResult.getCredential().getPassword()); + } else if(credentialRequestResult.getStatus().hasResolution()) + try { + credentialRequestResult.getStatus().startResolutionForResult(this, RESOLUTION_CHOOSER_CODE); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + else { + Log.e(getLoggingTag(), credentialRequestResult.getStatus()+""); + } + }); } private void showLanguage() { @@ -225,7 +305,15 @@ public class LoginActivity extends BaseActivity i getPresenter().login(InputHelper.toString(username), InputHelper.toString(password), InputHelper.toString(twoFactor), - isBasicAuth); + isBasicAuth, false); + } + } + + private void doLogin(String username, String password) { + if (progress == null || twoFactor == null || username == null || password == null) return; + if (progress.getVisibility() == View.GONE) { + pass = password; + getPresenter().login(username, password, "", isBasicAuth, true); } } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java index b35cdc8a..d02d7b01 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java @@ -23,6 +23,8 @@ public interface LoginMvp { void onEmptyPassword(boolean isEmpty); + void onSuccessfullyLoggedIn(Login userModel); + void onSuccessfullyLoggedIn(); } @@ -36,6 +38,6 @@ public interface LoginMvp { void onUserResponse(@Nullable Login response); - void login(@NonNull String username, @NonNull String password, @Nullable String twoFactorCode, boolean isBasicAuth); + void login(@NonNull String username, @NonNull String password, @Nullable String twoFactorCode, boolean isBasicAuth, @Nullable boolean ignore); } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java index 130069b5..e4cc9ceb 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java @@ -101,20 +101,23 @@ public class LoginPresenter extends BasePresenter implements Logi if (userModel != null) { userModel.setToken(PrefGetter.getToken()); userModel.save(userModel); - sendToView(LoginMvp.View::onSuccessfullyLoggedIn); + if(getView()!=null) + getView().onSuccessfullyLoggedIn(userModel); + else + sendToView(LoginMvp.View::onSuccessfullyLoggedIn); return; } sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); } @Override public void login(@NonNull String username, @NonNull String password, - @Nullable String twoFactorCode, boolean isBasicAuth) { + @Nullable String twoFactorCode, boolean isBasicAuth, boolean ignore) { boolean usernameIsEmpty = InputHelper.isEmpty(username); boolean passwordIsEmpty = InputHelper.isEmpty(password); if (getView() == null) return; - getView().onEmptyUserName(usernameIsEmpty); - getView().onEmptyPassword(passwordIsEmpty); - if (!usernameIsEmpty && !passwordIsEmpty) { + getView().onEmptyUserName(!ignore&&usernameIsEmpty); + getView().onEmptyPassword(!ignore&&passwordIsEmpty); + if ((!usernameIsEmpty && !passwordIsEmpty) || ignore) { String authToken = Credentials.basic(username, password); if (isBasicAuth) { AuthModel authModel = new AuthModel(); From 0f4eb9d58d0180c64dc5fa3e4531570c1b48fdcb Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Sat, 20 May 2017 06:12:03 -0400 Subject: [PATCH 5/6] Disable Google Smart Lock After Logout. So that you have the chance to switch accounts, Google Smart Lock will be disabled until a successful log in. --- app/src/main/java/com/fastaccess/ui/base/BaseActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java index cf6f8893..63e1b03d 100644 --- a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java +++ b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java @@ -143,8 +143,8 @@ public abstract class BaseActivity Date: Sat, 20 May 2017 06:14:18 -0400 Subject: [PATCH 6/6] Fix Issue #512. Previously starring was "staring", this fixes that. --- .../provider/tasks/git/GithubActionService.java | 8 ++++---- app/src/main/res/values/strings.xml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java b/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java index 164ec5b3..a8036c01 100644 --- a/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java +++ b/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java @@ -134,7 +134,7 @@ public class GithubActionService extends IntentService { private void starGist(@Nullable String id) { if (id != null) { - String msg = getString(R.string.staring, getString(R.string.gist)); + String msg = getString(R.string.starring, getString(R.string.gist)); RestProvider.getGistService() .starGist(id) .doOnSubscribe(() -> showNotification(msg)) @@ -146,7 +146,7 @@ public class GithubActionService extends IntentService { private void starRepo(@Nullable String id, @Nullable String login) { if (id != null && login != null) { - String msg = getString(R.string.staring, id); + String msg = getString(R.string.starring, id); RestProvider.getRepoService() .starRepo(login, id) .doOnSubscribe(() -> showNotification(msg)) @@ -158,7 +158,7 @@ public class GithubActionService extends IntentService { private void unStarGist(@Nullable String id) { if (id != null) { - String msg = getString(R.string.un_staring, getString(R.string.gist)); + String msg = getString(R.string.un_starring, getString(R.string.gist)); RestProvider.getGistService() .unStarGist(id) .doOnSubscribe(() -> showNotification(msg)) @@ -170,7 +170,7 @@ public class GithubActionService extends IntentService { private void unStarRepo(@Nullable String id, @Nullable String login) { if (id != null && login != null) { - String msg = getString(R.string.un_staring, id); + String msg = getString(R.string.un_starring, id); RestProvider.getRepoService() .unstarRepo(login, id) .doOnSubscribe(() -> showNotification(msg)) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5be3b945..64b895c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -280,8 +280,8 @@ Marking notification as read Forking gist Forking %s - Staring %s - Unstaring %s + Starring %s + Unstarring %s Unwatching %s Watching %s Login using your default browser (OAuth)