From a30e5bbeca94df2020e18b8e8e2a670eb5ea3a73 Mon Sep 17 00:00:00 2001 From: Kosh Date: Sun, 12 Mar 2017 06:21:59 +0800 Subject: [PATCH] re-implementing login flow where now FastHub has its own login screen. Improved overall spacing and dividers, validation for an unauthorized user to be directed to login screen, modified events actions to be displayed properly in feeds list and loads more things i can't remember. --- app/src/main/AndroidManifest.xml | 8 +- .../fastaccess/data/dao/AccessTokenModel.java | 30 +++- .../com/fastaccess/data/dao/AuthModel.java | 51 +++++++ .../data/service/UserRestService.java | 7 + .../provider/rest/LoginProvider.java | 55 +++++++ .../AuthenticationInterceptor.java | 21 +++ .../adapter/viewholder/FeedsViewHolder.java | 13 +- .../com/fastaccess/ui/base/BaseActivity.java | 8 ++ .../ui/base/BaseDialogFragment.java | 4 + .../com/fastaccess/ui/base/BaseFragment.java | 9 +- .../com/fastaccess/ui/base/mvp/BaseMvp.java | 2 + .../ui/base/mvp/presenter/BasePresenter.java | 9 ++ .../fastaccess/ui/modules/login/LoginMvp.java | 16 ++- .../ui/modules/login/LoginPresenter.java | 59 ++++---- .../ui/modules/login/LoginView.java | 96 +++++++------ .../fastaccess/ui/modules/main/MainView.java | 6 +- .../recyclerview/DynamicRecyclerView.java | 19 +-- .../recyclerview/InsetDividerDecoration.java | 15 +- .../layout-land/repo_file_header_layout.xml | 9 +- .../layout-large/repo_file_header_layout.xml | 10 +- .../main_layouts/layout/login_layout.xml | 135 +++++++++++++----- .../layout/small_grid_refresh_list.xml | 1 + .../layout/title_header_layout.xml | 9 +- .../layout/vertical_refresh_list.xml | 1 + .../other_layouts/layout/drawer_header.xml | 10 +- .../row_layouts/layout/comments_row_item.xml | 10 +- .../row_layouts/layout/feeds_row_item.xml | 5 +- .../layout/issue_detail_header_row_item.xml | 10 +- .../row_layouts/layout/issue_row_item.xml | 4 +- .../layout/issue_timeline_row_item.xml | 6 +- .../row_layouts/layout/releases_row_item.xml | 8 +- .../layout/repo_files_row_item.xml | 8 +- .../row_layouts/layout/repos_row_item.xml | 7 +- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/strings.xml | 24 ++-- app/src/main/res/values/styles.xml | 7 + 36 files changed, 494 insertions(+), 199 deletions(-) create mode 100644 app/src/main/java/com/fastaccess/data/dao/AuthModel.java create mode 100644 app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java create mode 100644 app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d6b5fb42..01452eaf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,7 +28,8 @@ android:name=".ui.modules.login.LoginView" android:configChanges="keyboard|orientation|screenSize" android:label="@string/app_name" - android:launchMode="singleTop"> + android:launchMode="singleTop" + android:theme="@style/LoginTheme"> @@ -132,9 +133,9 @@ + android:parentActivityName=".ui.modules.main.MainView" + android:theme="@style/WhenLargeTheme"> @@ -146,7 +147,6 @@ CREATOR = new Parcelable.Creator() { + @Override public AccessTokenModel createFromParcel(Parcel source) {return new AccessTokenModel(source);} + + @Override public AccessTokenModel[] newArray(int size) {return new AccessTokenModel[size];} + }; } diff --git a/app/src/main/java/com/fastaccess/data/dao/AuthModel.java b/app/src/main/java/com/fastaccess/data/dao/AuthModel.java new file mode 100644 index 00000000..70a95d4a --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/AuthModel.java @@ -0,0 +1,51 @@ +package com.fastaccess.data.dao; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * Created by Kosh on 12 Mar 2017, 3:16 AM + */ + +@Getter @Setter @NoArgsConstructor +public class AuthModel implements Parcelable { + + private String clientId; + private String clientSecret; + private String redirectUri; + private List scopes; + private String state; + private String note; + + @Override public int describeContents() { return 0; } + + @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.clientId); + dest.writeString(this.clientSecret); + dest.writeString(this.redirectUri); + dest.writeStringList(this.scopes); + dest.writeString(this.state); + dest.writeString(this.note); + } + + protected AuthModel(Parcel in) { + this.clientId = in.readString(); + this.clientSecret = in.readString(); + this.redirectUri = in.readString(); + this.scopes = in.createStringArrayList(); + this.state = in.readString(); + this.note = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override public AuthModel createFromParcel(Parcel source) {return new AuthModel(source);} + + @Override public AuthModel[] newArray(int size) {return new AuthModel[size];} + }; +} diff --git a/app/src/main/java/com/fastaccess/data/service/UserRestService.java b/app/src/main/java/com/fastaccess/data/service/UserRestService.java index 80a9639c..2fe2d8c6 100644 --- a/app/src/main/java/com/fastaccess/data/service/UserRestService.java +++ b/app/src/main/java/com/fastaccess/data/service/UserRestService.java @@ -3,6 +3,7 @@ package com.fastaccess.data.service; import android.support.annotation.NonNull; import com.fastaccess.data.dao.AccessTokenModel; +import com.fastaccess.data.dao.AuthModel; import com.fastaccess.data.dao.EventsModel; import com.fastaccess.data.dao.LoginModel; import com.fastaccess.data.dao.Pageable; @@ -10,6 +11,7 @@ import com.fastaccess.data.dao.RepoModel; import com.fastaccess.data.dao.UserModel; import retrofit2.Response; +import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; @@ -33,6 +35,11 @@ public interface UserRestService { @NonNull @Field("state") String state, @NonNull @Field("redirect_uri") String redirectUrl); + @PUT("authorizations/clients/{clientId}") Observable login(@NonNull @Path("clientId") String clientId, + @NonNull @Body AuthModel authModel); + + @DELETE("authorizations/{id}") Observable> deleteToken(@Path("id") long id); + @GET("user") Observable getUser(); @GET("users/{username}") Observable getUser(@Path("username") @NonNull String username); diff --git a/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java b/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java new file mode 100644 index 00000000..4a905e45 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java @@ -0,0 +1,55 @@ +package com.fastaccess.provider.rest; + +import android.support.annotation.NonNull; + +import com.fastaccess.BuildConfig; +import com.fastaccess.data.service.UserRestService; +import com.fastaccess.provider.rest.converters.GithubResponseConverter; +import com.fastaccess.provider.rest.interceptors.AuthenticationInterceptor; +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.lang.reflect.Modifier; + +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; + +/** + * Created by Kosh on 08 Feb 2017, 8:37 PM + */ + +public class LoginProvider { + + private final static Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) + .setDateFormat("yyyy-MM-dd HH:mm:ss") + .setPrettyPrinting() + .create(); + + private static OkHttpClient provideOkHttpClient(@NonNull String authToken) { + OkHttpClient.Builder client = new OkHttpClient.Builder(); + if (BuildConfig.DEBUG) { + client.addInterceptor(new HttpLoggingInterceptor() + .setLevel(HttpLoggingInterceptor.Level.BODY)); + } + client.addInterceptor(new AuthenticationInterceptor(authToken)); + return client.build(); + } + + private static Retrofit provideRetrofit(@NonNull String authToken) { + return new Retrofit.Builder() + .baseUrl(BuildConfig.REST_URL) + .client(provideOkHttpClient(authToken)) + .addConverterFactory(new GithubResponseConverter(gson)) + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .build(); + } + + @NonNull public static UserRestService getLoginRestService(@NonNull String authToken) { + return provideRetrofit(authToken).create(UserRestService.class); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.java b/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.java new file mode 100644 index 00000000..f5951a35 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.java @@ -0,0 +1,21 @@ +package com.fastaccess.provider.rest.interceptors; + +import java.io.IOException; + +import lombok.AllArgsConstructor; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +@AllArgsConstructor +public class AuthenticationInterceptor implements Interceptor { + + private String authToken; + + @Override public Response intercept(Chain chain) throws IOException { + Request original = chain.request(); + Request.Builder builder = original.newBuilder().header("Authorization", authToken); + Request request = builder.build(); + return chain.proceed(request); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java index cfc7e330..2d8d2a06 100644 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java @@ -7,6 +7,7 @@ import android.view.ViewGroup; import com.fastaccess.R; import com.fastaccess.data.dao.EventsModel; +import com.fastaccess.data.dao.types.EventsType; import com.fastaccess.helper.ParseDateFormat; import com.fastaccess.ui.widgets.AvatarLayout; import com.fastaccess.ui.widgets.FontTextView; @@ -41,10 +42,16 @@ public class FeedsViewHolder extends BaseViewHolder { avatar.setUrl(null, null); } SpannableBuilder spannableBuilder = SpannableBuilder.builder(); - spannableBuilder.append(eventsModel.getActor() != null ? eventsModel.getActor().getLogin() : "n/a").append(" "); + spannableBuilder.append(eventsModel.getActor() != null ? eventsModel.getActor().getLogin() : "N/A").append(" "); if (eventsModel.getType() != null) - spannableBuilder.bold(itemView.getResources().getString(eventsModel.getType().getType()).toLowerCase()).append(" "); - spannableBuilder.append(eventsModel.getRepo() != null ? eventsModel.getRepo().getName() : "n/a"); + spannableBuilder.bold(eventsModel.getPayload() != null ? eventsModel.getPayload().getAction() : "") + .append(eventsModel.getPayload() != null && eventsModel.getPayload().getAction() != null ? " " : ""); + if (eventsModel.getType() != EventsType.WatchEvent) { + spannableBuilder + .bold(itemView.getResources().getString(eventsModel.getType().getType()).toLowerCase()) + .append(" "); + } + spannableBuilder.append(eventsModel.getRepo() != null ? eventsModel.getRepo().getName() : "N/A"); title.setText(spannableBuilder); date.setText(ParseDateFormat.getTimeAgo(eventsModel.getCreatedAt())); } 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 4e296a0d..c7526d9c 100644 --- a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java +++ b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java @@ -12,6 +12,7 @@ import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.webkit.CookieManager; import android.widget.Toast; import com.fastaccess.BuildConfig; @@ -184,6 +185,13 @@ public abstract class BaseActivity extends TiPresenter impl @Override public void onError(@NonNull Throwable throwable) { throwable.printStackTrace(); + if (RestProvider.getErrorCode(throwable) == 401) { + sendToView(BaseMvp.FAView::onRequireLogin); + return; + } GitHubErrorResponse errorResponse = RestProvider.getErrorResponse(throwable); Logger.e(errorResponse); if (errorResponse != null && errorResponse.getMessage() != null) { @@ -57,4 +62,8 @@ public class BasePresenter extends TiPresenter impl .subscribe(onNext, this::onError, () -> apiCalled = true) ); } + + @StringRes private int getPrettifiedErrorMessage(@Nullable Throwable throwable) { + return 0; + } } 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 729a8cc2..a958a535 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 @@ -1,13 +1,11 @@ package com.fastaccess.ui.modules.login; -import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.fastaccess.data.dao.AccessTokenModel; import com.fastaccess.data.dao.LoginModel; import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; /** * Created by Kosh on 09 Nov 2016, 9:41 PM @@ -15,20 +13,24 @@ import com.fastaccess.ui.widgets.AppbarRefreshLayout; interface LoginMvp { - interface View extends BaseMvp.FAView, AppbarRefreshLayout.OnRefreshListener { + interface View extends BaseMvp.FAView { + + void onEmptyUserName(boolean isEmpty); + + void onEmptyPassword(boolean isEmpty); + void onSuccessfullyLoggedIn(); } interface Presenter extends BaseMvp.FAPresenter { - @Nullable String getCode(@NonNull String url); - - @NonNull Uri getAuthorizationUrl(); - void onGetToken(@NonNull String code); void onTokenResponse(@Nullable AccessTokenModel response); void onUserResponse(@Nullable LoginModel response); + + + void login(@NonNull String username, @NonNull String password); } } 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 8822370d..2912a2c1 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 @@ -1,51 +1,29 @@ package com.fastaccess.ui.modules.login; -import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.fastaccess.BuildConfig; import com.fastaccess.R; import com.fastaccess.data.dao.AccessTokenModel; +import com.fastaccess.data.dao.AuthModel; import com.fastaccess.data.dao.LoginModel; import com.fastaccess.helper.InputHelper; import com.fastaccess.helper.PrefGetter; +import com.fastaccess.provider.rest.LoginProvider; import com.fastaccess.provider.rest.RestProvider; import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import java.util.Arrays; + +import okhttp3.Credentials; + /** * Created by Kosh on 09 Nov 2016, 9:43 PM */ class LoginPresenter extends BasePresenter implements LoginMvp.Presenter { - @Nullable @Override public String getCode(@NonNull String url) { - Uri uri = Uri.parse(url); - if (uri != null && uri.toString().startsWith(BuildConfig.REDIRECT_URL)) { - String code = uri.getQueryParameter("code"); - if (code != null) { - return code; - } else if (uri.getQueryParameter("error") != null) { - sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); - } - } - return null; - } - - @NonNull @Override public Uri getAuthorizationUrl() { - return new Uri.Builder() - .scheme("https") - .authority("github.com") - .appendPath("login") - .appendPath("oauth") - .appendPath("authorize") - .appendQueryParameter("client_id", BuildConfig.GITHUB_CLIENT_ID) - .appendQueryParameter("redirect_uri", BuildConfig.REDIRECT_URL) - .appendQueryParameter("scope", "user,repo,gist,notifications") - .appendQueryParameter("state", BuildConfig.APPLICATION_ID) - .build(); - } - @Override public void onGetToken(@NonNull String code) { makeRestCall(RestProvider.getLoginRestService().getAccessToken(code, BuildConfig.GITHUB_CLIENT_ID, BuildConfig.GITHUB_SECRET, @@ -55,7 +33,7 @@ class LoginPresenter extends BasePresenter implements LoginMvp.Pr @Override public void onTokenResponse(@Nullable AccessTokenModel modelResponse) { if (modelResponse != null) { - String token = modelResponse.getAccessToken(); + String token = modelResponse.getToken(); if (!InputHelper.isEmpty(token)) { PrefGetter.setToken(token); makeRestCall(RestProvider.getUserService().getUser(), this::onUserResponse); @@ -74,4 +52,27 @@ class LoginPresenter extends BasePresenter implements LoginMvp.Pr } sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); } + + @Override public void login(@NonNull String username, @NonNull String password) { + boolean usernameIsEmpty = InputHelper.isEmpty(username); + boolean passwordIsEmpty = InputHelper.isEmpty(password); + if (getView() == null) return; + getView().onEmptyUserName(usernameIsEmpty); + getView().onEmptyPassword(passwordIsEmpty); + if (!usernameIsEmpty && !passwordIsEmpty) { + String authToken = Credentials.basic(username, password); + AuthModel authModel = new AuthModel(); + authModel.setScopes(Arrays.asList("user", "repo", "gist", "notifications")); + authModel.setNote(BuildConfig.APPLICATION_ID + "-" + authToken);//make it unique to FastHub. + authModel.setClientSecret(BuildConfig.GITHUB_SECRET); + makeRestCall(LoginProvider.getLoginRestService(authToken).login(BuildConfig.GITHUB_CLIENT_ID, authModel), tokenModel -> { + if (InputHelper.isEmpty(tokenModel.getToken())) { + makeRestCall(LoginProvider.getLoginRestService(authToken).deleteToken(tokenModel.getId()), + response -> login(username, password)); + } else { + onTokenResponse(tokenModel); + } + }); + } + } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginView.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginView.java index 2a936c0d..e14b50fb 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginView.java @@ -1,21 +1,22 @@ package com.fastaccess.ui.modules.login; -import android.annotation.SuppressLint; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; -import android.webkit.WebChromeClient; -import android.webkit.WebResourceRequest; -import android.webkit.WebView; -import android.webkit.WebViewClient; +import android.support.annotation.StringRes; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.TextInputEditText; +import android.support.design.widget.TextInputLayout; +import android.widget.ProgressBar; import com.fastaccess.R; +import com.fastaccess.helper.AnimHelper; +import com.fastaccess.helper.InputHelper; import com.fastaccess.ui.base.BaseActivity; import com.fastaccess.ui.modules.main.MainView; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; import butterknife.BindView; +import butterknife.OnClick; /** * Created by Kosh on 08 Feb 2017, 9:10 PM @@ -24,8 +25,12 @@ import butterknife.BindView; public class LoginView extends BaseActivity implements LoginMvp.View { - @BindView(R.id.webView) WebView webView; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; + @BindView(R.id.usernameEditText) TextInputEditText usernameEditText; + @BindView(R.id.username) TextInputLayout username; + @BindView(R.id.passwordEditText) TextInputEditText passwordEditText; + @BindView(R.id.password) TextInputLayout password; + @BindView(R.id.login) FloatingActionButton login; + @BindView(R.id.progress) ProgressBar progress; @Override protected int layout() { return R.layout.login_layout; @@ -47,8 +52,12 @@ public class LoginView extends BaseActivity imple return new LoginPresenter(); } - @Override public void onRefresh() { - webView.loadUrl(getPresenter().getAuthorizationUrl().toString()); + @Override public void onEmptyUserName(boolean isEmpty) { + username.setError(isEmpty ? getString(R.string.required_field) : null); + } + + @Override public void onEmptyPassword(boolean isEmpty) { + password.setError(isEmpty ? getString(R.string.required_field) : null); } @Override public void onSuccessfullyLoggedIn() { @@ -57,44 +66,41 @@ public class LoginView extends BaseActivity imple finish(); } - @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - refresh.setOnRefreshListener(this); - webView.getSettings().setSaveFormData(false); - webView.getSettings().setJavaScriptEnabled(true); - webView.setWebChromeClient(new WebChromeClient() { - @Override public void onProgressChanged(WebView view, int progress) { - super.onProgressChanged(view, progress); - if (progress == 100) { - refresh.setRefreshing(false); - } else if (progress < 100) { - refresh.setRefreshing(true); - } + } + + @OnClick(R.id.login) public void onClick() { + getPresenter().login(InputHelper.toString(username), InputHelper.toString(password)); + } + + @Override public void showErrorMessage(@NonNull String msgRes) { + hideProgress(); + super.showErrorMessage(msgRes); + } + + @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { + hideProgress(); + super.showMessage(titleRes, msgRes); + } + + @Override public void showProgress(@StringRes int resId) { + AnimHelper.animateVisibility(login, false, new AnimHelper.AnimationCallback() { + @Override public void onAnimationEnd() { + AnimHelper.animateVisibility(progress, true); } + + @Override public void onAnimationStart() {} }); + } + @Override public void hideProgress() { + AnimHelper.animateVisibility(progress, false, new AnimHelper.AnimationCallback() { + @Override public void onAnimationEnd() { + AnimHelper.animateVisibility(login, true); + } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - webView.setWebViewClient(new WebViewClient() { - @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - String code = getPresenter().getCode(request.getUrl().toString()); - if (code != null) { - getPresenter().onGetToken(code); - } - return false; - } - }); - } else { - webView.setWebViewClient(new WebViewClient() { - @SuppressWarnings("deprecation") @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - String code = getPresenter().getCode(url); - if (code != null) { - getPresenter().onGetToken(code); - } - return false; - } - }); - } - onRefresh(); + @Override public void onAnimationStart() {} + }); } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java index 250e7917..beafc0e4 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java @@ -13,7 +13,6 @@ import android.support.v4.widget.DrawerLayout; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.webkit.CookieManager; import android.widget.TextView; import android.widget.Toast; @@ -182,10 +181,7 @@ public class MainView extends BaseActivity implemen } @Override public void onLogout() { - CookieManager.getInstance().removeAllCookies(null); - PrefGetter.clear(); - LoginModel.deleteTable().execute(); - recreate(); + onRequireLogin(); } @Override public void openFasHubRepo() { diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java index dab9d940..dab30d86 100644 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java @@ -10,6 +10,7 @@ import android.util.AttributeSet; import android.view.View; import com.fastaccess.R; +import com.fastaccess.helper.ViewHelper; import com.fastaccess.ui.widgets.StateLayout; @@ -107,16 +108,18 @@ public class DynamicRecyclerView extends RecyclerView { } public void addKeyLineDivider() { - Resources resources = getResources(); - addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), - resources.getDimensionPixelSize(R.dimen.keyline_1), - ContextCompat.getColor(getContext(), R.color.divider))); + if (!ViewHelper.isTablet(getContext())) { + Resources resources = getResources(); + addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), + resources.getDimensionPixelSize(R.dimen.keyline_1), ContextCompat.getColor(getContext(), R.color.divider))); + } } public void addDivider() { - Resources resources = getResources(); - addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), - resources.getDimensionPixelSize(R.dimen.spacing_xs_large), - ContextCompat.getColor(getContext(), R.color.divider))); + if (!ViewHelper.isTablet(getContext())) { + Resources resources = getResources(); + addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), 0, + ContextCompat.getColor(getContext(), R.color.divider))); + } } } diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java index 993989cb..67e5ca7e 100644 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java @@ -35,15 +35,18 @@ class InsetDividerDecoration extends RecyclerView.ItemDecoration { boolean hasDividers = false; for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); + int position = parent.getChildAdapterPosition(child); if (child.isActivated() || (i + 1 < childCount && parent.getChildAt(i + 1).isActivated())) { continue; } - lines[i * 4] = inset + lm.getDecoratedLeft(child); - lines[(i * 4) + 2] = lm.getDecoratedRight(child); - int y = lm.getDecoratedBottom(child) + (int) child.getTranslationY() - height; - lines[(i * 4) + 1] = y; - lines[(i * 4) + 3] = y; - hasDividers = true; + if (position != (state.getItemCount() - 1)) { + lines[i * 4] = inset == 0 ? inset : inset + lm.getDecoratedLeft(child); + lines[(i * 4) + 2] = lm.getDecoratedRight(child); + int y = lm.getDecoratedBottom(child) + (int) child.getTranslationY() - height; + lines[(i * 4) + 1] = y; + lines[(i * 4) + 3] = y; + hasDividers = true; + } } if (hasDividers) { canvas.drawLines(lines, paint); diff --git a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml index 76888dd1..6c88d693 100644 --- a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml @@ -9,7 +9,6 @@ android:orientation="horizontal" android:paddingBottom="@dimen/spacing_micro" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_micro" tools:showIn="@layout/repo_file_layout"> @@ -25,6 +24,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/home" android:padding="@dimen/spacing_normal" @@ -35,7 +36,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginStart="@dimen/spacing_xs_large" android:orientation="horizontal" app:layoutManager="@string/linear_layout_manager" tools:listitem="@layout/file_path_row_item"/> @@ -53,6 +53,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:contentDescription="@string/switch_branch" android:padding="@dimen/spacing_normal" android:src="@drawable/ic_branch"/> @@ -62,8 +64,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginEnd="@dimen/spacing_xs_large" - android:layout_marginStart="@dimen/spacing_xs_large" + android:layout_marginEnd="@dimen/spacing_normal" android:layout_weight="1" android:spinnerMode="dialog" app:backgroundTint="?colorAccent" diff --git a/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml index 76888dd1..6eb3be72 100644 --- a/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml @@ -9,7 +9,6 @@ android:orientation="horizontal" android:paddingBottom="@dimen/spacing_micro" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_micro" tools:showIn="@layout/repo_file_layout"> @@ -25,6 +24,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/home" android:padding="@dimen/spacing_normal" @@ -35,7 +36,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginStart="@dimen/spacing_xs_large" + android:layout_marginEnd="@dimen/spacing_normal" android:orientation="horizontal" app:layoutManager="@string/linear_layout_manager" tools:listitem="@layout/file_path_row_item"/> @@ -53,6 +54,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:contentDescription="@string/switch_branch" android:padding="@dimen/spacing_normal" android:src="@drawable/ic_branch"/> @@ -62,8 +65,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginEnd="@dimen/spacing_xs_large" - android:layout_marginStart="@dimen/spacing_xs_large" + android:layout_marginEnd="@dimen/spacing_normal" android:layout_weight="1" android:spinnerMode="dialog" app:backgroundTint="?colorAccent" diff --git a/app/src/main/res/layouts/main_layouts/layout/login_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_layout.xml index 8eae9a47..3a4e392c 100644 --- a/app/src/main/res/layouts/main_layouts/layout/login_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/login_layout.xml @@ -1,52 +1,115 @@ - - + android:layout_gravity="center"> - + android:layout_margin="@dimen/spacing_s_large" + android:minHeight="350dp" + android:minWidth="250dp" + app:cardElevation="@dimen/spacing_normal"> - + android:orientation="vertical"> - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml b/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml index 4e975475..021367ec 100644 --- a/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml +++ b/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml @@ -14,6 +14,7 @@ android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent" + android:listDivider="@color/divider" app:layoutManager="@string/staggered_layout_manager" app:spanCount="@integer/small_spans"/> diff --git a/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml index c11d8bf9..5fec6a63 100644 --- a/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml @@ -10,20 +10,23 @@ android:clipToPadding="false" android:minHeight="?actionBarSize" android:orientation="horizontal" - android:padding="@dimen/spacing_xs_large" + android:paddingBottom="@dimen/spacing_xs_large" + android:paddingEnd="@dimen/spacing_xs_large" + android:paddingTop="@dimen/spacing_xs_large" app:layout_scrollFlags="scroll|enterAlways" tools:showIn="@layout/repo_pager_activity"> + android:layout_height="48dp" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin"/> diff --git a/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml b/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml index 0099a77a..db8530dc 100644 --- a/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml +++ b/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml @@ -10,18 +10,22 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_xs_large" android:orientation="horizontal" - android:padding="@dimen/spacing_xs_large"> + android:paddingBottom="@dimen/spacing_xs_large" + android:paddingEnd="@dimen/spacing_xs_large" + android:paddingTop="@dimen/spacing_xs_large"> + android:layout_height="@dimen/header_icon_zie" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin"/> @@ -27,7 +26,9 @@ + android:layout_height="48dp" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin"/> \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml index a71ab282..2f5a6ff7 100644 --- a/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml @@ -9,7 +9,6 @@ android:foreground="?android:selectableItemBackground" android:paddingBottom="@dimen/spacing_normal" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_normal" android:stateListAnimator="@animator/raise_selector"> @@ -22,13 +21,15 @@ android:id="@+id/avatarLayout" android:layout_width="@dimen/large_icon_zie" android:layout_height="@dimen/large_icon_zie" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:transitionName="@string/icon_transition"/> @@ -26,7 +25,9 @@ + android:layout_height="48dp" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin"/> diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml index 756c08ed..77288b95 100644 --- a/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml @@ -10,7 +10,6 @@ android:foreground="?android:selectableItemBackground" android:paddingBottom="@dimen/spacing_normal" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_normal" android:stateListAnimator="@animator/raise_selector"> @@ -25,12 +24,13 @@ android:layout_width="48dp" android:layout_height="48dp" android:visibility="gone" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" tools:visibility="visible"/> + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin"/> + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" + android:visibility="gone" + tools:visibility="visible"/> diff --git a/app/src/main/res/layouts/row_layouts/layout/repo_files_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/repo_files_row_item.xml index 864f6394..1ea70a9d 100644 --- a/app/src/main/res/layouts/row_layouts/layout/repo_files_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/repo_files_row_item.xml @@ -9,7 +9,6 @@ android:foreground="?android:selectableItemBackground" android:paddingBottom="@dimen/spacing_normal" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_normal" android:stateListAnimator="@animator/raise_selector"> @@ -23,6 +22,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/file" android:padding="@dimen/spacing_normal" @@ -32,6 +33,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginEnd="@dimen/spacing_normal" android:layout_weight="1" android:orientation="vertical"> @@ -40,8 +42,6 @@ style="@style/TextAppearance.AppCompat.Medium" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/spacing_xs_large" - android:layout_marginStart="@dimen/spacing_xs_large" android:ellipsize="end" android:maxLines="3" android:textColor="@color/primary_text" @@ -53,8 +53,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginEnd="@dimen/spacing_xs_large" - android:layout_marginStart="@dimen/spacing_xs_large" tools:text="10KB"/> diff --git a/app/src/main/res/layouts/row_layouts/layout/repos_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/repos_row_item.xml index d2ef9108..d55958ca 100644 --- a/app/src/main/res/layouts/row_layouts/layout/repos_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/repos_row_item.xml @@ -10,7 +10,6 @@ android:foreground="?android:selectableItemBackground" android:paddingBottom="@dimen/spacing_normal" android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" android:paddingTop="@dimen/spacing_normal" android:stateListAnimator="@animator/raise_selector"> @@ -24,12 +23,14 @@ android:id="@+id/avatarLayout" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginEnd="@dimen/avatar_margin" + android:layout_marginStart="@dimen/avatar_margin" + tools:visibility="visible" android:visibility="gone"/> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 3d765537..b134f239 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -26,4 +26,5 @@ 0dp @dimen/spacing_micro 1px + 12dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a866a82..0991f87a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -198,23 +198,23 @@ Committed Downloaded Followed - Created Gist - Wiki created - Commented on Issue - Issue Event + Gist + Wiki + Comment on Issue + Issue Member Open sourced - PR comment preview + PR comment Pushed - Team Event + Team Deleted Unknown - Commented on commit - Organization Event - Card event - Project event - PR preview - Repo Event + Comment on commit + Organization + Card + Project + PR + Repo Switch Branch Assignees Edit diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9b8a8114..7a0c13c8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -102,4 +102,11 @@ true + +