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 + +