diff --git a/README.md b/README.md
index cd664b35..17c374c0 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
[](https://gitea.com/gitnex/GitNex/releases)
[](https://drone.gitea.com/gitnex/GitNex)
[](https://crowdin.com/project/gitnex)
+[](https://discord.gg/FbSS4rf)
[
](https://www.patreon.com/mmarif)
[
](https://liberapay.com/mmarif/donate)
@@ -90,5 +91,6 @@ Open source libraries
- Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable
- Barteksc/AndroidPdfViewer
+- Mikepenz/fastadapter
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)
diff --git a/app/build.gradle b/app/build.gradle
index d6ea30b5..e2460f4a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -33,14 +33,15 @@ configurations {
dependencies {
def lifecycle_version = "2.2.0"
- final def markwon_version = '4.2.1'
+ 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"
@@ -79,4 +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"
+ //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/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/activities/CommitsActivity.java b/app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java
new file mode 100644
index 00000000..60df3de6
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java
@@ -0,0 +1,325 @@
+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.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+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.appcompat.widget.Toolbar;
+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.clients.RetrofitClient;
+import org.mian.gitnex.items.CommitsItems;
+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;
+import static com.mikepenz.fastadapter.adapters.ItemAdapter.items;
+
+/**
+ * Author M M Arif
+ */
+
+public class CommitsActivity extends BaseActivity implements ItemFilterListener {
+
+ private View.OnClickListener onClickListener;
+ private TextView noData;
+ private ProgressBar progressBar;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private String TAG = "CommitsActivity - ";
+ private int resultLimit = 50;
+ private boolean loadNextFlag = false;
+
+ private List items = new ArrayList<>();
+ private FastItemAdapter fastItemAdapter;
+ private ItemAdapter footerAdapter;
+ private EndlessRecyclerOnScrollListener endlessRecyclerOnScrollListener;
+
+ @Override
+ protected int getLayoutResourceId(){
+ return R.layout.activity_commits;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ TinyDB tinyDb = new TinyDB(getApplicationContext());
+ 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];
+
+ String branchName = getIntent().getStringExtra("branchName");
+
+ TextView toolbar_title = findViewById(R.id.toolbar_title);
+ toolbar_title.setMovementMethod(new ScrollingMovementMethod());
+ toolbar_title.setText(branchName);
+
+ ImageView closeActivity = findViewById(R.id.close);
+ noData = findViewById(R.id.noDataCommits);
+ progressBar = findViewById(R.id.progress_bar);
+ swipeRefreshLayout = findViewById(R.id.pullToRefresh);
+
+ RecyclerView recyclerView = findViewById(R.id.recyclerView);
+ recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
+ recyclerView.setHasFixedSize(true);
+
+ initCloseListener();
+ closeActivity.setOnClickListener(onClickListener);
+
+ fastItemAdapter = new FastItemAdapter<>();
+ fastItemAdapter.withSelectable(true);
+
+ footerAdapter = items();
+ //noinspection unchecked
+ fastItemAdapter.addAdapter(1, footerAdapter);
+
+ fastItemAdapter.getItemFilter().withFilterPredicate((IItemAdapter.Predicate) (item, constraint) -> item.getCommitTitle().toLowerCase().contains(Objects.requireNonNull(constraint).toString().toLowerCase()));
+
+ fastItemAdapter.getItemFilter().withItemFilterListener(this);
+
+ recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
+ recyclerView.setItemAnimator(new DefaultItemAnimator());
+ recyclerView.setAdapter(fastItemAdapter);
+
+ endlessRecyclerOnScrollListener = new EndlessRecyclerOnScrollListener(footerAdapter) {
+
+ @Override
+ public void onLoadMore(final int currentPage) {
+
+ loadNext(instanceUrl, instanceToken, repoOwner, repoName, currentPage, branchName);
+
+ }
+
+ };
+
+ swipeRefreshLayout.setOnRefreshListener(() -> {
+
+ progressBar.setVisibility(View.VISIBLE);
+ fastItemAdapter.clear();
+ endlessRecyclerOnScrollListener.resetPageCount();
+ swipeRefreshLayout.setRefreshing(false);
+
+ });
+
+ recyclerView.addOnScrollListener(endlessRecyclerOnScrollListener);
+
+ loadInitial(instanceUrl, instanceToken, repoOwner, repoName, branchName);
+
+ assert savedInstanceState != null;
+ fastItemAdapter.withSavedInstanceState(savedInstanceState);
+
+ }
+
+ private void loadInitial(String instanceUrl, String token, String repoOwner, String repoName, String branchName) {
+
+ Call> call = RetrofitClient
+ .getInstance(instanceUrl, getApplicationContext())
+ .getApiInterface()
+ .getRepositoryCommits(token, repoOwner, repoName, 1, branchName);
+
+ 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(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()));
+
+ }
+
+ 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, String branchName) {
+
+ footerAdapter.clear();
+ //noinspection unchecked
+ footerAdapter.add(new ProgressItem().withEnabled(false));
+ Handler handler = new Handler();
+
+ handler.postDelayed(() -> {
+
+ Call> call = RetrofitClient
+ .getInstance(instanceUrl, getApplicationContext())
+ .getApiInterface()
+ .getRepositoryCommits(token, repoOwner, repoName, currentPage + 1, branchName);
+
+ 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(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()));
+
+ }
+
+ 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 boolean onCreateOptionsMenu(Menu menu) {
+
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.search_menu, menu);
+
+ 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();
+ return super.onCreateOptionsMenu(menu);
+
+ }
+
+ @Override
+ public void itemsFiltered(@Nullable CharSequence constraint, @Nullable List results) {
+ endlessRecyclerOnScrollListener.disable();
+ }
+
+ @Override
+ public void onReset() {
+ endlessRecyclerOnScrollListener.enable();
+ }
+
+ private void initCloseListener() {
+ onClickListener = view -> {
+ getIntent().removeExtra("branchName");
+ finish();
+ };
+ }
+
+}
+
+
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 17ff3cef..dd0d177a 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/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
index 3259bbbf..ae249f77 100644
--- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
@@ -270,17 +270,18 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
case 4: // pull requests
fragment = new PullRequestsFragment();
break;
- case 5: // milestones
- return MilestonesFragment.newInstance(repoOwner, repoName);
- case 6: // labels
- return LabelsFragment.newInstance(repoOwner, repoName);
- case 7: // branches
+ case 5: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
- case 8: // releases
+ case 6: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
+ 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;
}
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" + mCtx.getResources().getString(R.string.commitLinkBranchesTab) + " "));
- holder.branchCommitHash.setMovementMethod(LinkMovementMethod.getInstance());
-
}
@Override
diff --git a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
index 1360a78a..556fcb0b 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
@@ -58,7 +58,7 @@ public class ClosedIssuesAdapter 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() {
+ @SuppressLint("SetTextI18n")
@Override
public void onNavigateBack(BreadcrumbItem item, int position) {
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/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/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
index e00149c3..75cc3cdf 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, @Query("sha") String branchName);
}
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