From c8164c56d0dac4c6d0b17a9a4aedde21ef8c5901 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Wed, 25 Mar 2020 19:43:40 +0500 Subject: [PATCH 1/7] Initial work on commits list using paging library --- app/build.gradle | 2 + .../gitnex/activities/RepoDetailActivity.java | 16 +- .../mian/gitnex/adapters/CommitsAdapter.java | 78 ++++++ .../gitnex/datasource/CommitsDataSource.java | 138 ++++++++++ .../datasource/CommitsDataSourceFactory.java | 52 ++++ .../gitnex/fragments/CommitsFragment.java | 98 +++++++ .../mian/gitnex/fragments/FilesFragment.java | 3 + .../mian/gitnex/interfaces/ApiInterface.java | 4 + .../java/org/mian/gitnex/models/Commits.java | 257 ++++++++++++++++++ .../gitnex/viewmodels/CommitsViewModel.java | 43 +++ .../main/res/layout/activity_repo_detail.xml | 6 + app/src/main/res/layout/fragment_commits.xml | 44 +++ app/src/main/res/layout/list_commits.xml | 37 +++ app/src/main/res/values/strings.xml | 2 + 14 files changed, 774 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java create mode 100644 app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java create mode 100644 app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java create mode 100644 app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java create mode 100644 app/src/main/java/org/mian/gitnex/models/Commits.java create mode 100644 app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java create mode 100644 app/src/main/res/layout/fragment_commits.xml create mode 100644 app/src/main/res/layout/list_commits.xml diff --git a/app/build.gradle b/app/build.gradle index d6ea30b5..ae5aaab8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,7 @@ configurations { dependencies { def lifecycle_version = "2.2.0" final def markwon_version = '4.2.1' + def paging_version = "2.1.2" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "androidx.appcompat:appcompat:1.1.0" @@ -79,4 +80,5 @@ dependencies { implementation "com.github.chrisbanes:PhotoView:2.3.0" implementation "com.pddstudio:highlightjs-android:1.5.0" implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1" + implementation "androidx.paging:paging-runtime:$paging_version" } diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java index 3259bbbf..dbbf34cb 100644 --- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java @@ -27,6 +27,7 @@ import org.mian.gitnex.R; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.fragments.BottomSheetRepoFragment; import org.mian.gitnex.fragments.BranchesFragment; +import org.mian.gitnex.fragments.CommitsFragment; import org.mian.gitnex.fragments.IssuesClosedFragment; import org.mian.gitnex.fragments.CollaboratorsFragment; import org.mian.gitnex.fragments.FilesFragment; @@ -270,15 +271,18 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF case 4: // pull requests fragment = new PullRequestsFragment(); break; - case 5: // milestones + case 5: // commits + fragment = new CommitsFragment(); + break; + case 6: // milestones return MilestonesFragment.newInstance(repoOwner, repoName); - case 6: // labels + case 7: // labels return LabelsFragment.newInstance(repoOwner, repoName); - case 7: // branches + case 8: // branches return BranchesFragment.newInstance(repoOwner, repoName); - case 8: // releases + case 9: // releases return ReleasesFragment.newInstance(repoOwner, repoName); - case 9: // collaborators + case 10: // collaborators return CollaboratorsFragment.newInstance(repoOwner, repoName); } return fragment; @@ -286,7 +290,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF @Override public int getCount() { - return 10; + return 11; } } diff --git a/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java new file mode 100644 index 00000000..a79e342c --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java @@ -0,0 +1,78 @@ +package org.mian.gitnex.adapters; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; +import org.mian.gitnex.R; +import org.mian.gitnex.models.Commits; + +/** + * Author M M Arif + */ + +public class CommitsAdapter extends PagedListAdapter { + + private Context mCtx; + + public CommitsAdapter(Context mCtx) { + + super(DIFF_CALLBACK); + this.mCtx = mCtx; + + } + + @NonNull + @Override + public CommitsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + + View view = LayoutInflater.from(mCtx).inflate(R.layout.list_commits, parent, false); + return new CommitsViewHolder(view); + + } + + @Override + public void onBindViewHolder(@NonNull CommitsViewHolder holder, int position) { + + Commits commit_ = getItem(position); + + if (commit_ != null) { + holder.commitTitle.setText(commit_.getCommit().getMessage()); + } + + } + + private static DiffUtil.ItemCallback DIFF_CALLBACK = + new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(Commits oldCommit, Commits newCommit) { + return oldCommit.getSha().equals(newCommit.getSha()); + } + + @SuppressLint("DiffUtilEquals") + @Override + public boolean areContentsTheSame(Commits oldCommit, @NonNull Commits newCommit) { + return oldCommit.equals(newCommit); + } + }; + + static class CommitsViewHolder extends RecyclerView.ViewHolder { + + TextView commitTitle; + + CommitsViewHolder(View itemView) { + + super(itemView); + commitTitle = itemView.findViewById(R.id.commitTitle); + + } + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java new file mode 100644 index 00000000..05725175 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java @@ -0,0 +1,138 @@ +package org.mian.gitnex.datasource; + +import android.content.Context; +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.paging.PageKeyedDataSource; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.models.Commits; +import java.util.List; +import java.util.Objects; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * Author M M Arif + */ + +public class CommitsDataSource extends PageKeyedDataSource { + + private String TAG = "CommitsDataSource"; + private Context ctx; + + private static final int FIRST_PAGE = 1; + + private String instanceUrl; + private String instanceToken; + private String owner; + private String repo; + + CommitsDataSource(Context ctx, String instanceUrl, String instanceToken, String owner, String repo) { + + this.ctx = ctx; + this.instanceUrl = instanceUrl; + this.instanceToken = instanceToken; + this.owner = owner; + this.repo = repo; + + } + + @Override + public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback callback) { + + RetrofitClient.getInstance(instanceUrl, ctx) + .getApiInterface() + .getRepositoryCommits(instanceToken, owner, repo, FIRST_PAGE) + .enqueue(new Callback>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.body() != null) { + + callback.onResult(response.body(), null, FIRST_PAGE + 1); + + } + + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, Objects.requireNonNull(t.getMessage())); + + } + }); + + } + + @Override + public void loadBefore(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { + + RetrofitClient.getInstance(instanceUrl, ctx) + .getApiInterface() + .getRepositoryCommits(instanceToken, owner, repo, params.key) + .enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + Integer adjacentKey = (params.key > 1) ? params.key - 1 : null; + + if (response.body() != null) { + + callback.onResult(response.body(), adjacentKey); + + } + + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, Objects.requireNonNull(t.getMessage())); + + } + + }); + + } + + @Override + public void loadAfter(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { + + RetrofitClient.getInstance(instanceUrl, ctx) + .getApiInterface() + .getRepositoryCommits(instanceToken, owner, repo, params.key) + .enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.body() != null) { + + boolean next = false; + if(response.body().size() > 0) { + next = true; + } + + Integer key = next ? params.key + 1 : null; + + callback.onResult(response.body(), key); + + } + + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, Objects.requireNonNull(t.getMessage())); + + } + + }); + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java new file mode 100644 index 00000000..5e0e8093 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java @@ -0,0 +1,52 @@ +package org.mian.gitnex.datasource; + +import android.content.Context; +import androidx.annotation.NonNull; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.DataSource; +import androidx.paging.PageKeyedDataSource; +import org.mian.gitnex.models.Commits; + +/** + * Author M M Arif + */ + +public class CommitsDataSourceFactory extends DataSource.Factory { + + private Context ctx; + private String instanceUrl; + private String instanceToken; + private String repoOwner; + private String repoName; + private int listLimit; + + public CommitsDataSourceFactory(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, int listLimit) { + + this.ctx = ctx; + this.instanceUrl = instanceUrl; + this.instanceToken = instanceToken; + this.repoOwner = repoOwner; + this.repoName = repoName; + this.listLimit = listLimit; + + } + + private MutableLiveData> itemLiveDataSource = new MutableLiveData<>(); + + @NonNull + @Override + public DataSource create() { + + CommitsDataSource itemDataSource = new CommitsDataSource(ctx, instanceUrl, instanceToken, repoOwner, repoName); + itemLiveDataSource.postValue(itemDataSource); + return itemDataSource; + + } + + public MutableLiveData> getItemLiveDataSource() { + + return itemLiveDataSource; + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java new file mode 100644 index 00000000..3c52b23f --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java @@ -0,0 +1,98 @@ +package org.mian.gitnex.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelProviders; +import androidx.paging.PagedList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import org.mian.gitnex.R; +import org.mian.gitnex.adapters.CommitsAdapter; +import org.mian.gitnex.models.Commits; +import org.mian.gitnex.util.TinyDB; +import org.mian.gitnex.viewmodels.CommitsViewModel; + +/** + * Author M M Arif + */ + +public class CommitsFragment extends Fragment { + + private CommitsViewModel commitsViewModel; + private CommitsAdapter commitsAdapter; + private SwipeRefreshLayout swipeRefreshLayout; + + private int listLimit = 50; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + final View v = inflater.inflate(R.layout.fragment_commits, container, false); + setHasOptionsMenu(true); + + TinyDB tinyDb = new TinyDB(getContext()); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + String repoFullName = tinyDb.getString("repoFullName"); + String[] parts = repoFullName.split("/"); + final String repoOwner = parts[0]; + final String repoName = parts[1]; + + TextView noDataCommits = v.findViewById(R.id.noDataCommits); + ProgressBar progressBar = v.findViewById(R.id.progress_bar); + swipeRefreshLayout = v.findViewById(R.id.pullToRefresh); + progressBar.setVisibility(View.GONE); + + RecyclerView recyclerView = v.findViewById(R.id.recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setHasFixedSize(true); + + //CommitsViewModel commitsViewModel = new ViewModelProvider(this).get(CommitsViewModel.class); + + commitsAdapter = new CommitsAdapter(getContext()); + + commitsViewModel = ViewModelProviders.of(this, new ViewModelProvider.Factory() { + + @NonNull + @Override + public VM create(@NonNull Class modelClass) { + //noinspection unchecked + return (VM) new CommitsViewModel (getContext(), instanceUrl, instanceToken, repoOwner, repoName, listLimit); + } + + }).get(CommitsViewModel.class); + + swipeRefreshLayout.setOnRefreshListener(() -> commitsViewModel.refresh()); + + //noinspection unchecked + commitsViewModel.itemPagedList.observe(getViewLifecycleOwner(), new Observer>() { + + @Override + public void onChanged(@Nullable PagedList items) { + + commitsAdapter.submitList(items); + swipeRefreshLayout.setRefreshing(false); + + } + + }); + + recyclerView.setAdapter(commitsAdapter); + return v; + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java index 8c3da1b2..458e4978 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java @@ -1,5 +1,6 @@ package org.mian.gitnex.fragments; +import android.annotation.SuppressLint; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -145,7 +146,9 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter final String finalDirName_ = dirName_; mBreadcrumbsView.addItem(createItem(dirName)); + //noinspection unchecked mBreadcrumbsView.setCallback(new DefaultBreadcrumbsCallback() { + @SuppressLint("SetTextI18n") @Override public void onNavigateBack(BreadcrumbItem item, int position) { diff --git a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java index e00149c3..06752497 100644 --- a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java +++ b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java @@ -3,6 +3,7 @@ package org.mian.gitnex.interfaces; import com.google.gson.JsonElement; import org.mian.gitnex.models.AddEmail; import org.mian.gitnex.models.Branches; +import org.mian.gitnex.models.Commits; import org.mian.gitnex.models.ExploreRepositories; import org.mian.gitnex.models.Files; import org.mian.gitnex.models.MergePullRequest; @@ -259,4 +260,7 @@ public interface ApiInterface { @POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request Call mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr); + + @GET("repos/{owner}/{repo}/commits") // get all commits + Call> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); } diff --git a/app/src/main/java/org/mian/gitnex/models/Commits.java b/app/src/main/java/org/mian/gitnex/models/Commits.java new file mode 100644 index 00000000..b166a861 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/models/Commits.java @@ -0,0 +1,257 @@ +package org.mian.gitnex.models; + +import java.util.List; + +/** + * Author M M Arif + */ + +public class Commits { + + private String url; + private String sha; + private String html_url; + private commitObject commit; + private authorObject author; + private committerObject committer; + private List parent; + + public String getUrl() { + return url; + } + + public String getSha() { + return sha; + } + + public String getHtml_url() { + return html_url; + } + + public static class commitObject { + + private String url; + private CommitAuthor author; + private CommitCommitter committer; + private String message; + private CommitTree tree; + + public static class CommitAuthor { + + String name; + String email; + String date; + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getDate() { + return date; + } + + } + + public static class CommitCommitter { + + String name; + String email; + String date; + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getDate() { + return date; + } + + } + + public static class CommitTree { + + String url; + String sha; + + public String getUrl() { + return url; + } + + public String getSha() { + return sha; + } + + } + + public String getUrl() { + return url; + } + + public String getMessage() { + return message; + } + + public CommitAuthor getAuthor() { + return author; + } + + public CommitCommitter getCommitter() { + return committer; + } + + public CommitTree getTree() { + return tree; + } + } + + public static class authorObject { + + private int id; + private String login; + private String full_name; + private String email; + private String avatar_url; + private String language; + private Boolean is_admin; + private String last_login; + private String created; + private String username; + + public int getId() { + return id; + } + + public String getLogin() { + return login; + } + + public String getFull_name() { + return full_name; + } + + public String getEmail() { + return email; + } + + public String getAvatar_url() { + return avatar_url; + } + + public String getLanguage() { + return language; + } + + public Boolean getIs_admin() { + return is_admin; + } + + public String getLast_login() { + return last_login; + } + + public String getCreated() { + return created; + } + + public String getUsername() { + return username; + } + } + + public static class committerObject { + + private int id; + private String login; + private String full_name; + private String email; + private String avatar_url; + private String language; + private Boolean is_admin; + private String last_login; + private String created; + private String username; + + public int getId() { + return id; + } + + public String getLogin() { + return login; + } + + public String getFull_name() { + return full_name; + } + + public String getEmail() { + return email; + } + + public String getAvatar_url() { + return avatar_url; + } + + public String getLanguage() { + return language; + } + + public Boolean getIs_admin() { + return is_admin; + } + + public String getLast_login() { + return last_login; + } + + public String getCreated() { + return created; + } + + public String getUsername() { + return username; + } + + } + + public static class parentObject { + + private String url; + private String sha; + + public String getUrl() { + return url; + } + + public String getSha() { + return sha; + } + } + + public commitObject getCommit() { + return commit; + } + + public authorObject getAuthor() { + return author; + } + + public committerObject getCommitter() { + return committer; + } + + public List getParent() { + return parent; + } + +} + + + diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java new file mode 100644 index 00000000..7545c607 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java @@ -0,0 +1,43 @@ +package org.mian.gitnex.viewmodels; + +import android.content.Context; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PageKeyedDataSource; +import androidx.paging.PagedList; +import org.mian.gitnex.datasource.CommitsDataSource; +import org.mian.gitnex.datasource.CommitsDataSourceFactory; +import org.mian.gitnex.models.Commits; +import java.util.Objects; + +/** + * Author M M Arif + */ + +public class CommitsViewModel extends ViewModel { + + private CommitsDataSourceFactory itemDataSourceFactory; + public LiveData itemPagedList; + + public CommitsViewModel(Context ctx, String instannceUrl, String instanceToken, String owner, String repo, int listLimit) { + + itemDataSourceFactory = new CommitsDataSourceFactory(ctx, instannceUrl, instanceToken, owner, repo, listLimit); + LiveData> liveDataSource = itemDataSourceFactory.getItemLiveDataSource(); + PagedList.Config pagedListConfig = + (new PagedList.Config.Builder()) + .setEnablePlaceholders(true) + .setPageSize(listLimit).build(); + //noinspection unchecked + itemPagedList = new LivePagedListBuilder(itemDataSourceFactory, pagedListConfig) + .build(); + + } + + public void refresh() { + + Objects.requireNonNull(itemDataSourceFactory.getItemLiveDataSource().getValue()).invalidate(); + + } + +} diff --git a/app/src/main/res/layout/activity_repo_detail.xml b/app/src/main/res/layout/activity_repo_detail.xml index ce6408e5..b482f8ba 100644 --- a/app/src/main/res/layout/activity_repo_detail.xml +++ b/app/src/main/res/layout/activity_repo_detail.xml @@ -74,6 +74,12 @@ android:layout_height="wrap_content" android:text="@string/tabPullRequests" /> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_commits.xml b/app/src/main/res/layout/list_commits.xml new file mode 100644 index 00000000..65665766 --- /dev/null +++ b/app/src/main/res/layout/list_commits.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bba9dfb9..f2e5a20b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -560,4 +560,6 @@ Share Issue Share Repository Create Repository + Commits + Commit Title From ea9025296ab84a01e43f8c2e077e2dd94de5e583 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Fri, 27 Mar 2020 23:59:24 +0500 Subject: [PATCH 2/7] final implementation and ui completion of commits list --- app/build.gradle | 11 +- .../mian/gitnex/adapters/CommitsAdapter.java | 78 ----- .../gitnex/datasource/CommitsDataSource.java | 138 --------- .../datasource/CommitsDataSourceFactory.java | 52 ---- .../gitnex/fragments/CommitsFragment.java | 286 +++++++++++++++--- .../gitnex/fragments/IssuesOpenFragment.java | 2 +- .../org/mian/gitnex/items/CommitsItems.java | 180 +++++++++++ .../java/org/mian/gitnex/models/Commits.java | 9 +- .../gitnex/viewmodels/CommitsViewModel.java | 43 --- app/src/main/res/layout/list_commits.xml | 50 ++- app/src/main/res/values/strings.xml | 2 + 11 files changed, 489 insertions(+), 362 deletions(-) delete mode 100644 app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java delete mode 100644 app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java delete mode 100644 app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java create mode 100644 app/src/main/java/org/mian/gitnex/items/CommitsItems.java delete mode 100644 app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java diff --git a/app/build.gradle b/app/build.gradle index ae5aaab8..e2460f4a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,15 +33,15 @@ configurations { dependencies { def lifecycle_version = "2.2.0" - final def markwon_version = '4.2.1' - def paging_version = "2.1.2" + def markwon_version = "4.2.1" + def fastadapter = "3.3.1" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "androidx.appcompat:appcompat:1.1.0" implementation "com.google.android.material:material:1.2.0-alpha05" implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.legacy:legacy-support-v4:1.0.0" - testImplementation 'junit:junit:4.13' + testImplementation "junit:junit:4.13" androidTestImplementation "androidx.test:runner:1.2.0" androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0" implementation "com.github.vihtarb:tooltip:0.2.0" @@ -80,5 +80,8 @@ dependencies { implementation "com.github.chrisbanes:PhotoView:2.3.0" implementation "com.pddstudio:highlightjs-android:1.5.0" implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1" - implementation "androidx.paging:paging-runtime:$paging_version" + //noinspection GradleDependency + implementation "com.mikepenz:fastadapter:$fastadapter" + implementation "com.mikepenz:fastadapter-commons:$fastadapter" + implementation "com.mikepenz:fastadapter-extensions:$fastadapter" } diff --git a/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java deleted file mode 100644 index a79e342c..00000000 --- a/app/src/main/java/org/mian/gitnex/adapters/CommitsAdapter.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.mian.gitnex.adapters; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; -import org.mian.gitnex.R; -import org.mian.gitnex.models.Commits; - -/** - * Author M M Arif - */ - -public class CommitsAdapter extends PagedListAdapter { - - private Context mCtx; - - public CommitsAdapter(Context mCtx) { - - super(DIFF_CALLBACK); - this.mCtx = mCtx; - - } - - @NonNull - @Override - public CommitsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - - View view = LayoutInflater.from(mCtx).inflate(R.layout.list_commits, parent, false); - return new CommitsViewHolder(view); - - } - - @Override - public void onBindViewHolder(@NonNull CommitsViewHolder holder, int position) { - - Commits commit_ = getItem(position); - - if (commit_ != null) { - holder.commitTitle.setText(commit_.getCommit().getMessage()); - } - - } - - private static DiffUtil.ItemCallback DIFF_CALLBACK = - new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(Commits oldCommit, Commits newCommit) { - return oldCommit.getSha().equals(newCommit.getSha()); - } - - @SuppressLint("DiffUtilEquals") - @Override - public boolean areContentsTheSame(Commits oldCommit, @NonNull Commits newCommit) { - return oldCommit.equals(newCommit); - } - }; - - static class CommitsViewHolder extends RecyclerView.ViewHolder { - - TextView commitTitle; - - CommitsViewHolder(View itemView) { - - super(itemView); - commitTitle = itemView.findViewById(R.id.commitTitle); - - } - - } - -} diff --git a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java deleted file mode 100644 index 05725175..00000000 --- a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSource.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.mian.gitnex.datasource; - -import android.content.Context; -import android.util.Log; -import androidx.annotation.NonNull; -import androidx.paging.PageKeyedDataSource; -import org.mian.gitnex.clients.RetrofitClient; -import org.mian.gitnex.models.Commits; -import java.util.List; -import java.util.Objects; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -/** - * Author M M Arif - */ - -public class CommitsDataSource extends PageKeyedDataSource { - - private String TAG = "CommitsDataSource"; - private Context ctx; - - private static final int FIRST_PAGE = 1; - - private String instanceUrl; - private String instanceToken; - private String owner; - private String repo; - - CommitsDataSource(Context ctx, String instanceUrl, String instanceToken, String owner, String repo) { - - this.ctx = ctx; - this.instanceUrl = instanceUrl; - this.instanceToken = instanceToken; - this.owner = owner; - this.repo = repo; - - } - - @Override - public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback callback) { - - RetrofitClient.getInstance(instanceUrl, ctx) - .getApiInterface() - .getRepositoryCommits(instanceToken, owner, repo, FIRST_PAGE) - .enqueue(new Callback>() { - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { - - if (response.body() != null) { - - callback.onResult(response.body(), null, FIRST_PAGE + 1); - - } - - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - - Log.e(TAG, Objects.requireNonNull(t.getMessage())); - - } - }); - - } - - @Override - public void loadBefore(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { - - RetrofitClient.getInstance(instanceUrl, ctx) - .getApiInterface() - .getRepositoryCommits(instanceToken, owner, repo, params.key) - .enqueue(new Callback>() { - - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { - - Integer adjacentKey = (params.key > 1) ? params.key - 1 : null; - - if (response.body() != null) { - - callback.onResult(response.body(), adjacentKey); - - } - - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - - Log.e(TAG, Objects.requireNonNull(t.getMessage())); - - } - - }); - - } - - @Override - public void loadAfter(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { - - RetrofitClient.getInstance(instanceUrl, ctx) - .getApiInterface() - .getRepositoryCommits(instanceToken, owner, repo, params.key) - .enqueue(new Callback>() { - - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { - - if (response.body() != null) { - - boolean next = false; - if(response.body().size() > 0) { - next = true; - } - - Integer key = next ? params.key + 1 : null; - - callback.onResult(response.body(), key); - - } - - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - - Log.e(TAG, Objects.requireNonNull(t.getMessage())); - - } - - }); - - } - -} diff --git a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java b/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java deleted file mode 100644 index 5e0e8093..00000000 --- a/app/src/main/java/org/mian/gitnex/datasource/CommitsDataSourceFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.mian.gitnex.datasource; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.DataSource; -import androidx.paging.PageKeyedDataSource; -import org.mian.gitnex.models.Commits; - -/** - * Author M M Arif - */ - -public class CommitsDataSourceFactory extends DataSource.Factory { - - private Context ctx; - private String instanceUrl; - private String instanceToken; - private String repoOwner; - private String repoName; - private int listLimit; - - public CommitsDataSourceFactory(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, int listLimit) { - - this.ctx = ctx; - this.instanceUrl = instanceUrl; - this.instanceToken = instanceToken; - this.repoOwner = repoOwner; - this.repoName = repoName; - this.listLimit = listLimit; - - } - - private MutableLiveData> itemLiveDataSource = new MutableLiveData<>(); - - @NonNull - @Override - public DataSource create() { - - CommitsDataSource itemDataSource = new CommitsDataSource(ctx, instanceUrl, instanceToken, repoOwner, repoName); - itemLiveDataSource.postValue(itemDataSource); - return itemDataSource; - - } - - public MutableLiveData> getItemLiveDataSource() { - - return itemLiveDataSource; - - } - -} diff --git a/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java index 3c52b23f..2b48e2ee 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java @@ -1,39 +1,59 @@ package org.mian.gitnex.fragments; import android.os.Bundle; +import android.os.Handler; +import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import androidx.lifecycle.ViewModelProviders; -import androidx.paging.PagedList; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.mikepenz.fastadapter.IItemAdapter; +import com.mikepenz.fastadapter.adapters.ItemAdapter; +import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter; +import com.mikepenz.fastadapter.listeners.ItemFilterListener; +import com.mikepenz.fastadapter_extensions.items.ProgressItem; +import com.mikepenz.fastadapter_extensions.scroll.EndlessRecyclerOnScrollListener; import org.mian.gitnex.R; -import org.mian.gitnex.adapters.CommitsAdapter; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.items.CommitsItems; import org.mian.gitnex.models.Commits; import org.mian.gitnex.util.TinyDB; -import org.mian.gitnex.viewmodels.CommitsViewModel; +import java.util.ArrayList; +import java.util.List; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import static com.mikepenz.fastadapter.adapters.ItemAdapter.items; /** * Author M M Arif */ -public class CommitsFragment extends Fragment { +public class CommitsFragment extends Fragment implements ItemFilterListener { - private CommitsViewModel commitsViewModel; - private CommitsAdapter commitsAdapter; + private TextView noData; + private ProgressBar progressBar; private SwipeRefreshLayout swipeRefreshLayout; + private String TAG = "CommitsFragment - "; + private int resultLimit = 50; + private boolean loadNextFlag = false; - private int listLimit = 50; + private List items = new ArrayList<>(); + private FastItemAdapter fastItemAdapter; + private ItemAdapter footerAdapter; + private EndlessRecyclerOnScrollListener endlessRecyclerOnScrollListener; @Nullable @Override @@ -51,48 +71,244 @@ public class CommitsFragment extends Fragment { final String repoOwner = parts[0]; final String repoName = parts[1]; - TextView noDataCommits = v.findViewById(R.id.noDataCommits); - ProgressBar progressBar = v.findViewById(R.id.progress_bar); + noData = v.findViewById(R.id.noDataCommits); + progressBar = v.findViewById(R.id.progress_bar); swipeRefreshLayout = v.findViewById(R.id.pullToRefresh); - progressBar.setVisibility(View.GONE); RecyclerView recyclerView = v.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setHasFixedSize(true); - //CommitsViewModel commitsViewModel = new ViewModelProvider(this).get(CommitsViewModel.class); - - commitsAdapter = new CommitsAdapter(getContext()); - - commitsViewModel = ViewModelProviders.of(this, new ViewModelProvider.Factory() { - - @NonNull - @Override - public VM create(@NonNull Class modelClass) { - //noinspection unchecked - return (VM) new CommitsViewModel (getContext(), instanceUrl, instanceToken, repoOwner, repoName, listLimit); - } - - }).get(CommitsViewModel.class); - - swipeRefreshLayout.setOnRefreshListener(() -> commitsViewModel.refresh()); + fastItemAdapter = new FastItemAdapter<>(); + fastItemAdapter.withSelectable(true); + footerAdapter = items(); //noinspection unchecked - commitsViewModel.itemPagedList.observe(getViewLifecycleOwner(), new Observer>() { + fastItemAdapter.addAdapter(1, footerAdapter); + + fastItemAdapter.getItemFilter().withFilterPredicate(new IItemAdapter.Predicate() { @Override - public void onChanged(@Nullable PagedList items) { + public boolean filter(@NonNull CommitsItems item, CharSequence constraint) { - commitsAdapter.submitList(items); - swipeRefreshLayout.setRefreshing(false); + return item.getCommitTitle().toString().toLowerCase().contains(constraint.toString().toLowerCase()); } }); - recyclerView.setAdapter(commitsAdapter); + fastItemAdapter.getItemFilter().withItemFilterListener(this); + + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setItemAnimator(new DefaultItemAnimator()); + recyclerView.setAdapter(fastItemAdapter); + + endlessRecyclerOnScrollListener = new EndlessRecyclerOnScrollListener(footerAdapter) { + + @Override + public void onLoadMore(final int currentPage) { + + loadNext(instanceUrl, instanceToken, repoOwner, repoName, currentPage); + + } + + }; + + swipeRefreshLayout.setOnRefreshListener(() -> { + + progressBar.setVisibility(View.VISIBLE); + fastItemAdapter.clear(); + endlessRecyclerOnScrollListener.resetPageCount(); + swipeRefreshLayout.setRefreshing(false); + + }); + + recyclerView.addOnScrollListener(endlessRecyclerOnScrollListener); + + loadInitial(instanceUrl, instanceToken, repoOwner, repoName); + + assert savedInstanceState != null; + fastItemAdapter.withSavedInstanceState(savedInstanceState); + return v; } + private void loadInitial(String instanceUrl, String token, String repoOwner, String repoName) { + + Call> call = RetrofitClient + .getInstance(instanceUrl, getContext()) + .getApiInterface() + .getRepositoryCommits(token, repoOwner, repoName, 1); + + call.enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.isSuccessful()) { + + assert response.body() != null; + + if(response.body().size() > 0) { + + if(response.body().size() == resultLimit) { + loadNextFlag = true; + } + + for (int i = 0; i < response.body().size(); i++) { + + items.add(new CommitsItems(getContext()).withNewItems(response.body().get(i).getCommit().getMessage(), response.body().get(i).getHtml_url(), + response.body().get(i).getCommit().getCommitter().getName(), response.body().get(i).getCommit().getCommitter().getDate())); + + } + + fastItemAdapter.add(items); + + } + else { + + noData.setVisibility(View.VISIBLE); + + } + + progressBar.setVisibility(View.GONE); + + } + else { + + Log.e(TAG, String.valueOf(response.code())); + + } + + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, t.toString()); + + } + + }); + + } + + private void loadNext(String instanceUrl, String token, String repoOwner, String repoName, final int currentPage) { + + footerAdapter.clear(); + //noinspection unchecked + footerAdapter.add(new ProgressItem().withEnabled(false)); + Handler handler = new Handler(); + + handler.postDelayed(new Runnable() { + + @Override + public void run() { + + Call> call = RetrofitClient + .getInstance(instanceUrl, getContext()) + .getApiInterface() + .getRepositoryCommits(token, repoOwner, repoName, currentPage + 1); + + call.enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.isSuccessful()) { + + assert response.body() != null; + + if (response.body().size() > 0) { + + loadNextFlag = response.body().size() == resultLimit; + + for (int i = 0; i < response.body().size(); i++) { + + fastItemAdapter.add(fastItemAdapter.getAdapterItemCount(), new CommitsItems(getContext()).withNewItems(response.body().get(i).getCommit().getMessage(), + response.body().get(i).getHtml_url(), response.body().get(i).getCommit().getCommitter().getName(), + response.body().get(i).getCommit().getCommitter().getDate())); + + } + + footerAdapter.clear(); + + } + else { + + footerAdapter.clear(); + } + + progressBar.setVisibility(View.GONE); + + } + else { + + Log.e(TAG, String.valueOf(response.code())); + + } + + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, t.toString()); + + } + + }); + + } + + }, 1000); + + if(!loadNextFlag) { + + footerAdapter.clear(); + + } + + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + + inflater.inflate(R.menu.search_menu, menu); + super.onCreateOptionsMenu(menu, inflater); + + MenuItem searchItem = menu.findItem(R.id.action_search); + androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView(); + searchView.setImeOptions(EditorInfo.IME_ACTION_DONE); + + searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() { + + @Override + public boolean onQueryTextSubmit(String query) { + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + fastItemAdapter.filter(newText); + return true; + } + + }); + + endlessRecyclerOnScrollListener.enable(); + + } + + @Override + public void itemsFiltered(@Nullable CharSequence constraint, @Nullable List results) { + endlessRecyclerOnScrollListener.disable(); + } + + @Override + public void onReset() { + endlessRecyclerOnScrollListener.enable(); + } + } diff --git a/app/src/main/java/org/mian/gitnex/fragments/IssuesOpenFragment.java b/app/src/main/java/org/mian/gitnex/fragments/IssuesOpenFragment.java index cf5100b2..46b70dbc 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/IssuesOpenFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/IssuesOpenFragment.java @@ -51,7 +51,7 @@ public class IssuesOpenFragment extends Fragment { private int pageSize = 1; private TextView noDataIssues; private int resultLimit = 50; - private String requestType = "issues" ; + private String requestType = "issues"; @Nullable @Override diff --git a/app/src/main/java/org/mian/gitnex/items/CommitsItems.java b/app/src/main/java/org/mian/gitnex/items/CommitsItems.java new file mode 100644 index 00000000..bfa2a69f --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/items/CommitsItems.java @@ -0,0 +1,180 @@ +package org.mian.gitnex.items; + +import android.content.Context; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.view.View; +import android.widget.TextView; +import androidx.annotation.NonNull; +import com.mikepenz.fastadapter.FastAdapter; +import com.mikepenz.fastadapter.items.AbstractItem; +import org.mian.gitnex.R; +import org.mian.gitnex.helpers.ClickListener; +import org.mian.gitnex.helpers.TimeHelper; +import org.mian.gitnex.util.TinyDB; +import org.ocpsoft.prettytime.PrettyTime; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +/** + * Author M M Arif + */ + +public class CommitsItems extends AbstractItem { + + final private Context ctx; + private String commitTitle; + private String commitHtmlUrl; + private String commitCommitter; + private Date commitDate; + + private boolean isSelectable = true; + + public CommitsItems(Context ctx) { + this.ctx = ctx; + } + + public CommitsItems withNewItems(String commitTitle, String commitHtmlUrl, String commitCommitter, Date commitDate) { + + this.setNewItems(commitTitle, commitHtmlUrl, commitCommitter, commitDate); + return this; + + } + + private void setNewItems(String commitTitle, String commitHtmlUrl, String commitCommitter, Date commitDate) { + + this.commitTitle = commitTitle; + this.commitHtmlUrl = commitHtmlUrl; + this.commitCommitter = commitCommitter; + this.commitDate = commitDate; + + } + + public String getCommitTitle() { + return commitTitle; + } + + private String getCommitHtmlUrl() { + return commitHtmlUrl; + } + + private String getcommitCommitter() { + return commitCommitter; + } + + private Date getcommitDate() { + return commitDate; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public CommitsItems withEnabled(boolean enabled) { + return null; + } + + @Override + public boolean isSelectable() { + return isSelectable; + } + + @Override + public CommitsItems withSelectable(boolean selectable) { + + this.isSelectable = selectable; + return this; + + } + + @Override + public int getType() { + return R.id.commitList; + } + + @Override + public int getLayoutRes() { + return R.layout.list_commits; + } + + @NonNull + @Override + public CommitsItems.ViewHolder getViewHolder(@NonNull View v) { + + return new CommitsItems.ViewHolder(v); + + } + + public class ViewHolder extends FastAdapter.ViewHolder { + + final TinyDB tinyDb = new TinyDB(ctx); + final String locale = tinyDb.getString("locale"); + final String timeFormat = tinyDb.getString("dateFormat"); + + TextView commitTitleVw; + TextView commitCommitterVw; + TextView commitDateVw; + TextView commitHtmlUrlVw; + + public ViewHolder(View itemView) { + + super(itemView); + + commitTitleVw = itemView.findViewById(R.id.commitTitleVw); + commitCommitterVw = itemView.findViewById(R.id.commitCommitterVw); + commitDateVw = itemView.findViewById(R.id.commitDateVw); + commitHtmlUrlVw = itemView.findViewById(R.id.commitHtmlUrlVw); + + } + + @Override + public void bindView(CommitsItems item, @NonNull List payloads) { + + commitTitleVw.setText(item.getCommitTitle()); + commitCommitterVw.setText(ctx.getString(R.string.commitCommittedBy, item.getcommitCommitter())); + + switch (timeFormat) { + case "pretty": { + PrettyTime prettyTime = new PrettyTime(new Locale(locale)); + String createdTime = prettyTime.format(item.getcommitDate()); + commitDateVw.setText(createdTime); + commitDateVw.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(item.getcommitDate()), ctx)); + break; + } + case "normal": { + DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + ctx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale)); + String createdTime = formatter.format(item.getcommitDate()); + commitDateVw.setText(createdTime); + break; + } + case "normal1": { + DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + ctx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale)); + String createdTime = formatter.format(item.getcommitDate()); + commitDateVw.setText(createdTime); + break; + } + } + + commitHtmlUrlVw.setText(Html.fromHtml("" + ctx.getResources().getString(R.string.viewInBrowser) + " ")); + commitHtmlUrlVw.setMovementMethod(LinkMovementMethod.getInstance()); + + } + + @Override + public void unbindView(@NonNull CommitsItems item) { + + commitTitleVw.setText(null); + commitCommitterVw.setText(null); + commitDateVw.setText(null); + commitHtmlUrlVw.setText(null); + + } + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/models/Commits.java b/app/src/main/java/org/mian/gitnex/models/Commits.java index b166a861..dd64133e 100644 --- a/app/src/main/java/org/mian/gitnex/models/Commits.java +++ b/app/src/main/java/org/mian/gitnex/models/Commits.java @@ -1,5 +1,6 @@ package org.mian.gitnex.models; +import java.util.Date; import java.util.List; /** @@ -40,7 +41,7 @@ public class Commits { String name; String email; - String date; + Date date; public String getName() { return name; @@ -50,7 +51,7 @@ public class Commits { return email; } - public String getDate() { + public Date getDate() { return date; } @@ -60,7 +61,7 @@ public class Commits { String name; String email; - String date; + Date date; public String getName() { return name; @@ -70,7 +71,7 @@ public class Commits { return email; } - public String getDate() { + public Date getDate() { return date; } diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java deleted file mode 100644 index 7545c607..00000000 --- a/app/src/main/java/org/mian/gitnex/viewmodels/CommitsViewModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.mian.gitnex.viewmodels; - -import android.content.Context; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.ViewModel; -import androidx.paging.LivePagedListBuilder; -import androidx.paging.PageKeyedDataSource; -import androidx.paging.PagedList; -import org.mian.gitnex.datasource.CommitsDataSource; -import org.mian.gitnex.datasource.CommitsDataSourceFactory; -import org.mian.gitnex.models.Commits; -import java.util.Objects; - -/** - * Author M M Arif - */ - -public class CommitsViewModel extends ViewModel { - - private CommitsDataSourceFactory itemDataSourceFactory; - public LiveData itemPagedList; - - public CommitsViewModel(Context ctx, String instannceUrl, String instanceToken, String owner, String repo, int listLimit) { - - itemDataSourceFactory = new CommitsDataSourceFactory(ctx, instannceUrl, instanceToken, owner, repo, listLimit); - LiveData> liveDataSource = itemDataSourceFactory.getItemLiveDataSource(); - PagedList.Config pagedListConfig = - (new PagedList.Config.Builder()) - .setEnablePlaceholders(true) - .setPageSize(listLimit).build(); - //noinspection unchecked - itemPagedList = new LivePagedListBuilder(itemDataSourceFactory, pagedListConfig) - .build(); - - } - - public void refresh() { - - Objects.requireNonNull(itemDataSourceFactory.getItemLiveDataSource().getValue()).invalidate(); - - } - -} diff --git a/app/src/main/res/layout/list_commits.xml b/app/src/main/res/layout/list_commits.xml index 65665766..776865f7 100644 --- a/app/src/main/res/layout/list_commits.xml +++ b/app/src/main/res/layout/list_commits.xml @@ -2,9 +2,10 @@ + android:background="?attr/primaryBackgroundColor"> + + + + + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:orientation="horizontal"> + + + + + + + android:textSize="14sp" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2e5a20b..b8d6c0a1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -506,6 +506,7 @@ private public Default + View in Browser Translate GitNex with Crowdin @@ -562,4 +563,5 @@ Create Repository Commits Commit Title + Committed by %1$s From 21aae88e62e47a7b895d4a38378d84c0ddb5debf Mon Sep 17 00:00:00 2001 From: M M Arif Date: Sat, 28 Mar 2020 15:52:09 +0500 Subject: [PATCH 3/7] Refactor naming convention for better findings --- .../gitnex/activities/RepoDetailActivity.java | 20 ++++++++--------- .../gitnex/adapters/AdminGetUsersAdapter.java | 2 +- .../mian/gitnex/adapters/BranchesAdapter.java | 2 +- .../gitnex/adapters/ClosedIssuesAdapter.java | 2 +- .../gitnex/adapters/CollaboratorsAdapter.java | 2 +- .../adapters/ExploreRepositoriesAdapter.java | 3 +-- .../mian/gitnex/adapters/FilesAdapter.java | 2 +- .../gitnex/adapters/FilesDiffAdapter.java | 2 +- .../mian/gitnex/adapters/IssuesAdapter.java | 2 +- .../mian/gitnex/adapters/LabelsAdapter.java | 3 +-- .../gitnex/adapters/MembersByOrgAdapter.java | 2 +- .../gitnex/adapters/MilestonesAdapter.java | 2 +- .../gitnex/adapters/MyReposListAdapter.java | 3 +-- .../adapters/OrganizationsListAdapter.java | 2 +- .../gitnex/adapters/ProfileEmailsAdapter.java | 2 +- .../adapters/ProfileFollowersAdapter.java | 2 +- .../adapters/ProfileFollowingAdapter.java | 2 +- .../gitnex/adapters/PullRequestsAdapter.java | 2 +- .../mian/gitnex/adapters/ReleasesAdapter.java | 2 +- .../adapters/RepoStargazersAdapter.java | 2 +- .../gitnex/adapters/RepoWatchersAdapter.java | 2 +- .../gitnex/adapters/ReposListAdapter.java | 3 +-- .../adapters/RepositoriesByOrgAdapter.java | 3 +-- .../adapters/StarredReposListAdapter.java | 2 +- .../adapters/TeamMembersByOrgAdapter.java | 2 +- .../gitnex/adapters/TeamsByOrgAdapter.java | 2 +- .../gitnex/adapters/UserSearchAdapter.java | 2 +- .../main/res/layout/activity_repo_detail.xml | 22 +++++++------------ ...in_users_list.xml => list_admin_users.xml} | 0 .../{branches_list.xml => list_branches.xml} | 0 ...rators_list.xml => list_collaborators.xml} | 0 ...arch.xml => list_collaborators_search.xml} | 0 .../layout/{files_list.xml => list_files.xml} | 0 ...es_diffs_list.xml => list_files_diffs.xml} | 0 .../{repo_issues_list.xml => list_issues.xml} | 0 .../{labels_list.xml => list_labels.xml} | 0 ...y_org_list.xml => list_members_by_org.xml} | 0 ...st.xml => list_members_by_team_by_org.xml} | 0 ...ilestones_list.xml => list_milestones.xml} | 0 .../{my_repos_list.xml => list_my_repos.xml} | 0 ...ations_list.xml => list_organizations.xml} | 0 .../layout/{repo_pr_list.xml => list_pr.xml} | 0 ...mails_list.xml => list_profile_emails.xml} | 0 ...rs_list.xml => list_profile_followers.xml} | 0 ...ng_list.xml => list_profile_following.xml} | 0 .../{releases_list.xml => list_releases.xml} | 0 ...zers_list.xml => list_repo_stargazers.xml} | 0 ...tchers_list.xml => list_repo_watchers.xml} | 0 .../layout/{repos_list.xml => list_repos.xml} | 0 ..._list.xml => list_repositories_by_org.xml} | 0 ..._repos_list.xml => list_starred_repos.xml} | 0 ..._by_org_list.xml => list_teams_by_org.xml} | 0 52 files changed, 43 insertions(+), 56 deletions(-) rename app/src/main/res/layout/{admin_users_list.xml => list_admin_users.xml} (100%) rename app/src/main/res/layout/{branches_list.xml => list_branches.xml} (100%) rename app/src/main/res/layout/{collaborators_list.xml => list_collaborators.xml} (100%) rename app/src/main/res/layout/{collaborators_list_search.xml => list_collaborators_search.xml} (100%) rename app/src/main/res/layout/{files_list.xml => list_files.xml} (100%) rename app/src/main/res/layout/{files_diffs_list.xml => list_files_diffs.xml} (100%) rename app/src/main/res/layout/{repo_issues_list.xml => list_issues.xml} (100%) rename app/src/main/res/layout/{labels_list.xml => list_labels.xml} (100%) rename app/src/main/res/layout/{members_by_org_list.xml => list_members_by_org.xml} (100%) rename app/src/main/res/layout/{members_by_team_by_org_list.xml => list_members_by_team_by_org.xml} (100%) rename app/src/main/res/layout/{milestones_list.xml => list_milestones.xml} (100%) rename app/src/main/res/layout/{my_repos_list.xml => list_my_repos.xml} (100%) rename app/src/main/res/layout/{organizations_list.xml => list_organizations.xml} (100%) rename app/src/main/res/layout/{repo_pr_list.xml => list_pr.xml} (100%) rename app/src/main/res/layout/{profile_emails_list.xml => list_profile_emails.xml} (100%) rename app/src/main/res/layout/{profile_followers_list.xml => list_profile_followers.xml} (100%) rename app/src/main/res/layout/{profile_following_list.xml => list_profile_following.xml} (100%) rename app/src/main/res/layout/{releases_list.xml => list_releases.xml} (100%) rename app/src/main/res/layout/{repo_stargazers_list.xml => list_repo_stargazers.xml} (100%) rename app/src/main/res/layout/{repo_watchers_list.xml => list_repo_watchers.xml} (100%) rename app/src/main/res/layout/{repos_list.xml => list_repos.xml} (100%) rename app/src/main/res/layout/{repositories_by_org_list.xml => list_repositories_by_org.xml} (100%) rename app/src/main/res/layout/{starred_repos_list.xml => list_starred_repos.xml} (100%) rename app/src/main/res/layout/{teams_by_org_list.xml => list_teams_by_org.xml} (100%) diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java index dbbf34cb..7e6652b6 100644 --- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java @@ -271,26 +271,24 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF case 4: // pull requests fragment = new PullRequestsFragment(); break; - case 5: // commits - fragment = new CommitsFragment(); - break; - case 6: // milestones - return MilestonesFragment.newInstance(repoOwner, repoName); - case 7: // labels - return LabelsFragment.newInstance(repoOwner, repoName); - case 8: // branches + case 5: // branches return BranchesFragment.newInstance(repoOwner, repoName); - case 9: // releases + case 6: // releases return ReleasesFragment.newInstance(repoOwner, repoName); - case 10: // collaborators + case 7: // milestones + return MilestonesFragment.newInstance(repoOwner, repoName); + case 8: // labels + return LabelsFragment.newInstance(repoOwner, repoName); + case 9: // collaborators return CollaboratorsFragment.newInstance(repoOwner, repoName); } + assert fragment != null; return fragment; } @Override public int getCount() { - return 11; + return 10; } } diff --git a/app/src/main/java/org/mian/gitnex/adapters/AdminGetUsersAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/AdminGetUsersAdapter.java index cd88823c..ac4e67a3 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/AdminGetUsersAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/AdminGetUsersAdapter.java @@ -57,7 +57,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter LayoutInflater inflater = LayoutInflater.from(context); if(viewType == TYPE_LOAD){ - return new IssuesHolder(inflater.inflate(R.layout.repo_issues_list, parent,false)); + return new IssuesHolder(inflater.inflate(R.layout.list_issues, parent,false)); } else { return new LoadHolder(inflater.inflate(R.layout.row_load,parent,false)); diff --git a/app/src/main/java/org/mian/gitnex/adapters/LabelsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/LabelsAdapter.java index e6200440..d4ec1ed7 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/LabelsAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/LabelsAdapter.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import androidx.annotation.NonNull; -import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.widget.PopupMenu; import androidx.recyclerview.widget.RecyclerView; @@ -123,7 +122,7 @@ public class LabelsAdapter extends RecyclerView.Adapter + android:text="@string/tab_text_branches" /> + + - - - - Date: Sat, 28 Mar 2020 17:44:45 +0500 Subject: [PATCH 4/7] Remove commits tab, moved under branch. Commits are under branches now. Fixes search ui along the way --- app/src/main/AndroidManifest.xml | 1 + .../CommitsActivity.java} | 159 ++++++++++-------- .../gitnex/activities/RepoDetailActivity.java | 1 - .../mian/gitnex/adapters/BranchesAdapter.java | 22 ++- .../mian/gitnex/interfaces/ApiInterface.java | 2 +- ...ctivity_add_collaborator_to_repository.xml | 4 +- .../res/layout/activity_admin_get_users.xml | 4 +- app/src/main/res/layout/activity_commits.xml | 86 ++++++++++ .../main/res/layout/activity_create_issue.xml | 4 +- .../main/res/layout/activity_create_label.xml | 4 +- .../res/layout/activity_create_new_user.xml | 4 +- .../res/layout/activity_create_release.xml | 4 +- .../layout/activity_create_team_by_org.xml | 4 +- app/src/main/res/layout/activity_credits.xml | 4 +- .../main/res/layout/activity_edit_issue.xml | 4 +- .../main/res/layout/activity_file_diff.xml | 4 +- .../main/res/layout/activity_file_view.xml | 4 +- .../main/res/layout/activity_issue_detail.xml | 3 +- .../layout/activity_merge_pull_request.xml | 4 +- app/src/main/res/layout/activity_new_file.xml | 4 +- .../res/layout/activity_new_milestone.xml | 4 +- .../res/layout/activity_new_organization.xml | 4 +- app/src/main/res/layout/activity_new_repo.xml | 4 +- .../main/res/layout/activity_org_detail.xml | 2 +- .../res/layout/activity_org_team_members.xml | 4 +- .../res/layout/activity_profile_email.xml | 4 +- .../res/layout/activity_reply_to_issue.xml | 4 +- .../main/res/layout/activity_repo_detail.xml | 2 +- .../res/layout/activity_repo_stargazers.xml | 4 +- .../res/layout/activity_repo_watchers.xml | 4 +- app/src/main/res/layout/activity_sponsors.xml | 4 +- app/src/main/res/layout/fragment_commits.xml | 44 ----- app/src/main/res/layout/list_branches.xml | 8 +- app/src/main/res/layout/list_commits.xml | 8 + app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/themes.xml | 2 + 36 files changed, 273 insertions(+), 158 deletions(-) rename app/src/main/java/org/mian/gitnex/{fragments/CommitsFragment.java => activities/CommitsActivity.java} (62%) create mode 100644 app/src/main/res/layout/activity_commits.xml delete mode 100644 app/src/main/res/layout/fragment_commits.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a3415c93..d029de5d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -73,6 +73,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java b/app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java similarity index 62% rename from app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java rename to app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java index 2b48e2ee..60df3de6 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/CommitsFragment.java +++ b/app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java @@ -1,20 +1,20 @@ -package org.mian.gitnex.fragments; +package org.mian.gitnex.activities; import android.os.Bundle; import android.os.Handler; +import android.text.method.ScrollingMovementMethod; import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; +import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; +import androidx.appcompat.widget.Toolbar; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -32,6 +32,7 @@ import org.mian.gitnex.models.Commits; import org.mian.gitnex.util.TinyDB; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -41,12 +42,13 @@ import static com.mikepenz.fastadapter.adapters.ItemAdapter.items; * Author M M Arif */ -public class CommitsFragment extends Fragment implements ItemFilterListener { +public class CommitsActivity extends BaseActivity implements ItemFilterListener { + private View.OnClickListener onClickListener; private TextView noData; private ProgressBar progressBar; private SwipeRefreshLayout swipeRefreshLayout; - private String TAG = "CommitsFragment - "; + private String TAG = "CommitsActivity - "; private int resultLimit = 50; private boolean loadNextFlag = false; @@ -55,14 +57,19 @@ public class CommitsFragment extends Fragment implements ItemFilterListener(); fastItemAdapter.withSelectable(true); @@ -86,20 +103,11 @@ public class CommitsFragment extends Fragment implements ItemFilterListener() { - - @Override - public boolean filter(@NonNull CommitsItems item, CharSequence constraint) { - - return item.getCommitTitle().toString().toLowerCase().contains(constraint.toString().toLowerCase()); - - } - - }); + fastItemAdapter.getItemFilter().withFilterPredicate((IItemAdapter.Predicate) (item, constraint) -> item.getCommitTitle().toLowerCase().contains(Objects.requireNonNull(constraint).toString().toLowerCase())); fastItemAdapter.getItemFilter().withItemFilterListener(this); - recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setAdapter(fastItemAdapter); @@ -108,7 +116,7 @@ public class CommitsFragment extends Fragment implements ItemFilterListener> call = RetrofitClient - .getInstance(instanceUrl, getContext()) + .getInstance(instanceUrl, getApplicationContext()) .getApiInterface() - .getRepositoryCommits(token, repoOwner, repoName, 1); + .getRepositoryCommits(token, repoOwner, repoName, 1, branchName); call.enqueue(new Callback>() { @@ -158,7 +164,7 @@ public class CommitsFragment extends Fragment implements ItemFilterListener { - @Override - public void run() { + Call> call = RetrofitClient + .getInstance(instanceUrl, getApplicationContext()) + .getApiInterface() + .getRepositoryCommits(token, repoOwner, repoName, currentPage + 1, branchName); - Call> call = RetrofitClient - .getInstance(instanceUrl, getContext()) - .getApiInterface() - .getRepositoryCommits(token, repoOwner, repoName, currentPage + 1); + call.enqueue(new Callback>() { - call.enqueue(new Callback>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { + if (response.isSuccessful()) { - if (response.isSuccessful()) { + assert response.body() != null; - assert response.body() != null; + if (response.body().size() > 0) { - if (response.body().size() > 0) { + loadNextFlag = response.body().size() == resultLimit; - loadNextFlag = response.body().size() == resultLimit; + for (int i = 0; i < response.body().size(); i++) { - for (int i = 0; i < response.body().size(); i++) { - - fastItemAdapter.add(fastItemAdapter.getAdapterItemCount(), new CommitsItems(getContext()).withNewItems(response.body().get(i).getCommit().getMessage(), - response.body().get(i).getHtml_url(), response.body().get(i).getCommit().getCommitter().getName(), - response.body().get(i).getCommit().getCommitter().getDate())); - - } - - footerAdapter.clear(); + fastItemAdapter.add(fastItemAdapter.getAdapterItemCount(), new CommitsItems(getApplicationContext()).withNewItems(response.body().get(i).getCommit().getMessage(), + response.body().get(i).getHtml_url(), response.body().get(i).getCommit().getCommitter().getName(), + response.body().get(i).getCommit().getCommitter().getDate())); } - else { - footerAdapter.clear(); - } - - progressBar.setVisibility(View.GONE); + footerAdapter.clear(); } else { - Log.e(TAG, String.valueOf(response.code())); - + footerAdapter.clear(); } + progressBar.setVisibility(View.GONE); + } + else { - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - - Log.e(TAG, t.toString()); + Log.e(TAG, String.valueOf(response.code())); } - }); + } - } + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + + Log.e(TAG, t.toString()); + + } + + }); }, 1000); @@ -273,10 +274,10 @@ public class CommitsFragment extends Fragment implements ItemFilterListener { + getIntent().removeExtra("branchName"); + finish(); + }; + } + } + + diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java index 7e6652b6..ae249f77 100644 --- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java @@ -27,7 +27,6 @@ import org.mian.gitnex.R; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.fragments.BottomSheetRepoFragment; import org.mian.gitnex.fragments.BranchesFragment; -import org.mian.gitnex.fragments.CommitsFragment; import org.mian.gitnex.fragments.IssuesClosedFragment; import org.mian.gitnex.fragments.CollaboratorsFragment; import org.mian.gitnex.fragments.FilesFragment; diff --git a/app/src/main/java/org/mian/gitnex/adapters/BranchesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/BranchesAdapter.java index 472566d3..70a5ac39 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/BranchesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/BranchesAdapter.java @@ -1,16 +1,17 @@ package org.mian.gitnex.adapters; import android.content.Context; -import android.text.Html; -import android.text.method.LinkMovementMethod; +import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import org.mian.gitnex.R; +import org.mian.gitnex.activities.CommitsActivity; import org.mian.gitnex.models.Branches; import org.mian.gitnex.util.TinyDB; import java.util.List; +import java.util.Objects; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; @@ -27,14 +28,23 @@ public class BranchesAdapter extends RecyclerView.Adapter" + mCtx.getResources().getString(R.string.commitLinkBranchesTab) + " ")); - holder.branchCommitHash.setMovementMethod(LinkMovementMethod.getInstance()); - } @Override diff --git a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java index 06752497..75cc3cdf 100644 --- a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java +++ b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java @@ -262,5 +262,5 @@ public interface ApiInterface { Call mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr); @GET("repos/{owner}/{repo}/commits") // get all commits - Call> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); + Call> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("sha") String branchName); } diff --git a/app/src/main/res/layout/activity_add_collaborator_to_repository.xml b/app/src/main/res/layout/activity_add_collaborator_to_repository.xml index c0112fc8..d55cc514 100644 --- a/app/src/main/res/layout/activity_add_collaborator_to_repository.xml +++ b/app/src/main/res/layout/activity_add_collaborator_to_repository.xml @@ -6,8 +6,10 @@ android:background="?attr/primaryBackgroundColor"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_create_issue.xml b/app/src/main/res/layout/activity_create_issue.xml index edcc5a29..b9bb3f5e 100644 --- a/app/src/main/res/layout/activity_create_issue.xml +++ b/app/src/main/res/layout/activity_create_issue.xml @@ -7,8 +7,10 @@ android:background="?attr/primaryBackgroundColor"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> + android:layout_height="wrap_content" + android:theme="@style/Widget.AppCompat.SearchView"> - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/list_branches.xml b/app/src/main/res/layout/list_branches.xml index 885565d3..27a9c518 100644 --- a/app/src/main/res/layout/list_branches.xml +++ b/app/src/main/res/layout/list_branches.xml @@ -29,16 +29,16 @@ android:layout_height="wrap_content" android:textIsSelectable="true" android:textColor="?attr/primaryTextColor" - android:textSize="16sp" /> + android:textSize="14sp" /> + android:textColor="@color/lightBlue" + android:text="@string/viewCommits" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout/list_commits.xml b/app/src/main/res/layout/list_commits.xml index 776865f7..21856768 100644 --- a/app/src/main/res/layout/list_commits.xml +++ b/app/src/main/res/layout/list_commits.xml @@ -70,4 +70,12 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8d6c0a1..2e1d38b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -562,6 +562,7 @@ Share Repository Create Repository Commits - Commit Title + Branch Commits Committed by %1$s + View Commits diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 8a26b19c..7b25c1ad 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -6,6 +6,7 @@ @color/colorPrimary monospace @color/colorAccent + @color/colorWhite @color/colorWhite @color/colorPrimary @@ -28,6 +29,7 @@ @color/colorPrimary monospace @color/colorAccent + @color/lightThemeTextColor @color/lightThemeTextColor @color/lightThemeBackground From d52ff1557f68c857e0bd365b1b8d741449901487 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Sat, 28 Mar 2020 19:49:08 +0500 Subject: [PATCH 5/7] Fix login issue with internet access. Better solution to check internet connection with broadcast receiver. Prioritize token login. --- .../mian/gitnex/activities/LoginActivity.java | 52 +++++++----- .../mian/gitnex/helpers/NetworkObserver.java | 82 +++++++++++++++++++ app/src/main/res/layout/activity_login.xml | 33 ++++---- 3 files changed, 132 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/org/mian/gitnex/helpers/NetworkObserver.java diff --git a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java index 5136b096..bd033d42 100644 --- a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java @@ -23,6 +23,7 @@ import androidx.appcompat.app.AlertDialog; import com.tooltip.Tooltip; import org.mian.gitnex.R; import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.NetworkObserver; import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.VersionCheck; import org.mian.gitnex.models.GiteaVersion; @@ -65,7 +66,7 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener super.onCreate(savedInstanceState); TinyDB tinyDb = new TinyDB(getApplicationContext()); - boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext()); + NetworkObserver networkMonitor = new NetworkObserver(this); loginButton = findViewById(R.id.login_button); instanceUrlET = findViewById(R.id.instance_url); @@ -105,30 +106,39 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener info_button.setOnClickListener(infoListener); - if(!connToInternet) { + loginMethod.setOnCheckedChangeListener((group, checkedId) -> { - Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection)); - return; + if(checkedId == R.id.loginToken) { - } + loginUidET.setVisibility(View.GONE); + loginPassword.setVisibility(View.GONE); + otpCode.setVisibility(View.GONE); + otpInfo.setVisibility(View.GONE); + loginTokenCode.setVisibility(View.VISIBLE); - loginMethod.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - if(checkedId == R.id.loginUsernamePassword){ - loginUidET.setVisibility(View.VISIBLE); - loginPassword.setVisibility(View.VISIBLE); - otpCode.setVisibility(View.VISIBLE); - otpInfo.setVisibility(View.VISIBLE); - loginTokenCode.setVisibility(View.GONE); - } else { - loginUidET.setVisibility(View.GONE); - loginPassword.setVisibility(View.GONE); - otpCode.setVisibility(View.GONE); - otpInfo.setVisibility(View.GONE); - loginTokenCode.setVisibility(View.VISIBLE); - } } + else { + + loginUidET.setVisibility(View.VISIBLE); + loginPassword.setVisibility(View.VISIBLE); + otpCode.setVisibility(View.VISIBLE); + otpInfo.setVisibility(View.VISIBLE); + loginTokenCode.setVisibility(View.GONE); + + } + + }); + + networkMonitor.onInternetStateListener(isAvailable -> { + + if(isAvailable) { + enableProcessButton(); + } + else { + disableProcessButton(); + Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection)); + } + }); //login_button.setOnClickListener(this); diff --git a/app/src/main/java/org/mian/gitnex/helpers/NetworkObserver.java b/app/src/main/java/org/mian/gitnex/helpers/NetworkObserver.java new file mode 100644 index 00000000..6d557f20 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/helpers/NetworkObserver.java @@ -0,0 +1,82 @@ +package org.mian.gitnex.helpers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; + +/** + * Author M M Arif + */ + +public class NetworkObserver implements LifecycleObserver { + + private ConnectivityManager mConnectivityMgr; + private Context mContext; + private NetworkStateReceiver mNetworkStateReceiver; + + public interface ConnectionStateListener { + void onAvailable(boolean isAvailable); + } + + public NetworkObserver(Context context) { + mContext = context; + mConnectivityMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + ((AppCompatActivity) mContext).getLifecycle().addObserver(this); + } + + + public void onInternetStateListener(ConnectionStateListener listener) { + + mNetworkStateReceiver = new NetworkStateReceiver(listener); + IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mNetworkStateReceiver, intentFilter); + + } + + + @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) + public void onDestroy() { + + ((AppCompatActivity) mContext).getLifecycle().removeObserver(this); + + if (mNetworkStateReceiver != null) { + mContext.unregisterReceiver(mNetworkStateReceiver); + } + + } + + + public class NetworkStateReceiver extends BroadcastReceiver { + + ConnectionStateListener mListener; + + public NetworkStateReceiver(ConnectionStateListener listener) { + mListener = listener; + } + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getExtras() != null) { + NetworkInfo activeNetworkInfo = mConnectivityMgr.getActiveNetworkInfo(); + + if (activeNetworkInfo != null && activeNetworkInfo.getState() == NetworkInfo.State.CONNECTED) { + + mListener.onAvailable(true); // connected + + } else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) { + + mListener.onAvailable(false); // disconnected + + } + } + } + } + +} diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 69d2daa1..00ab253e 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -45,20 +45,21 @@ android:background="@drawable/shape_inputs" android:orientation="vertical"> - + + @@ -129,7 +130,8 @@ android:textColorHint="?attr/hintColor" android:textColorHighlight="?attr/hintColor" android:hint="@string/userName" - android:inputType="text" /> + android:inputType="text" + android:visibility="gone" /> + android:inputType="textPassword" + android:visibility="gone" /> + android:inputType="number" + android:visibility="gone" /> + android:visibility="visible" /> + android:gravity="end" + android:visibility="gone" />