mirror of https://codeberg.org/gitnex/GitNex.git
Fix repository forks pagination and filter
This commit is contained in:
parent
1571d98359
commit
3a733ce906
|
@ -4,28 +4,20 @@ import android.annotation.SuppressLint;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
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 androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.gitnex.tea4j.v2.models.Repository;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.adapters.RepoForksAdapter;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import org.mian.gitnex.viewmodels.RepositoryForksViewModel;
|
||||
|
||||
/**
|
||||
* @author M M Arif
|
||||
|
@ -33,13 +25,8 @@ import retrofit2.Response;
|
|||
public class RepoForksActivity extends BaseActivity {
|
||||
|
||||
private ActivityRepoForksBinding activityRepoForksBinding;
|
||||
private final String TAG = "RepositoryForks";
|
||||
|
||||
private int resultLimit;
|
||||
private int pageSize = 1;
|
||||
private List<Repository> forksList;
|
||||
private RepoForksAdapter adapter;
|
||||
|
||||
private RepositoryContext repository;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
|
@ -55,15 +42,11 @@ public class RepoForksActivity extends BaseActivity {
|
|||
setSupportActionBar(toolbar);
|
||||
|
||||
repository = RepositoryContext.fromIntent(getIntent());
|
||||
final String repoOwner = repository.getOwner();
|
||||
final String repoName = repository.getName();
|
||||
|
||||
activityRepoForksBinding.toolbarTitle.setText(
|
||||
ctx.getResources().getString(R.string.infoTabRepoForksCount));
|
||||
|
||||
activityRepoForksBinding.close.setOnClickListener(v -> finish());
|
||||
resultLimit = Constants.getCurrentResultLimit(ctx);
|
||||
forksList = new ArrayList<>();
|
||||
|
||||
activityRepoForksBinding.pullToRefresh.setOnRefreshListener(
|
||||
() ->
|
||||
|
@ -73,128 +56,77 @@ public class RepoForksActivity extends BaseActivity {
|
|||
pageSize = 1;
|
||||
activityRepoForksBinding.pullToRefresh.setRefreshing(
|
||||
false);
|
||||
loadInitial(repoOwner, repoName, pageSize, resultLimit);
|
||||
adapter.notifyDataChanged();
|
||||
fetchData();
|
||||
activityRepoForksBinding.progressBar.setVisibility(
|
||||
View.VISIBLE);
|
||||
},
|
||||
200));
|
||||
|
||||
adapter = new RepoForksAdapter(ctx, forksList);
|
||||
adapter.setLoadMoreListener(
|
||||
() ->
|
||||
activityRepoForksBinding.recyclerView.post(
|
||||
() -> {
|
||||
if (forksList.size() == resultLimit
|
||||
|| pageSize == resultLimit) {
|
||||
|
||||
int page = (forksList.size() + resultLimit) / resultLimit;
|
||||
loadMore(repoOwner, repoName, page, resultLimit);
|
||||
}
|
||||
}));
|
||||
150));
|
||||
|
||||
activityRepoForksBinding.recyclerView.setHasFixedSize(true);
|
||||
activityRepoForksBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
|
||||
activityRepoForksBinding.recyclerView.setAdapter(adapter);
|
||||
|
||||
loadInitial(repoOwner, repoName, pageSize, resultLimit);
|
||||
fetchData();
|
||||
}
|
||||
|
||||
private void loadInitial(String repoOwner, String repoName, int pageSize, int resultLimit) {
|
||||
private void fetchData() {
|
||||
|
||||
Call<List<Repository>> call =
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
.listForks(repoOwner, repoName, pageSize, resultLimit);
|
||||
RepositoryForksViewModel repositoryForksViewModel =
|
||||
new ViewModelProvider(this).get(RepositoryForksViewModel.class);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
repositoryForksViewModel
|
||||
.getForksList(repository.getOwner(), repository.getName(), ctx)
|
||||
.observe(
|
||||
this,
|
||||
forksListMain -> {
|
||||
adapter = new RepoForksAdapter(ctx, forksListMain);
|
||||
adapter.setLoadMoreListener(
|
||||
new RepoForksAdapter.OnLoadMoreListener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Repository>> call,
|
||||
@NonNull Response<List<Repository>> response) {
|
||||
@Override
|
||||
public void onLoadMore() {
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
pageSize += 1;
|
||||
repositoryForksViewModel.loadMore(
|
||||
repository.getOwner(),
|
||||
repository.getName(),
|
||||
pageSize,
|
||||
ctx,
|
||||
adapter);
|
||||
activityRepoForksBinding.progressBar.setVisibility(
|
||||
View.VISIBLE);
|
||||
}
|
||||
|
||||
assert response.body() != null;
|
||||
@Override
|
||||
public void onLoadFinished() {
|
||||
|
||||
if (response.body().size() > 0) {
|
||||
forksList.clear();
|
||||
forksList.addAll(response.body());
|
||||
adapter.notifyDataChanged();
|
||||
activityRepoForksBinding.progressBar.setVisibility(
|
||||
View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
if (adapter.getItemCount() > 0) {
|
||||
activityRepoForksBinding.recyclerView.setAdapter(adapter);
|
||||
activityRepoForksBinding.noData.setVisibility(View.GONE);
|
||||
} else {
|
||||
forksList.clear();
|
||||
adapter.notifyDataChanged();
|
||||
activityRepoForksBinding.recyclerView.setAdapter(adapter);
|
||||
activityRepoForksBinding.noData.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
activityRepoForksBinding.progressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
Log.e(TAG, String.valueOf(response.code()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Repository>> call, @NonNull Throwable t) {
|
||||
Log.e(TAG, t.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMore(String repoOwner, String repoName, int page, int resultLimit) {
|
||||
|
||||
activityRepoForksBinding.progressLoadMore.setVisibility(View.VISIBLE);
|
||||
|
||||
Call<List<Repository>> call =
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
.listForks(repoOwner, repoName, page, resultLimit);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Repository>> call,
|
||||
@NonNull Response<List<Repository>> response) {
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
|
||||
// remove loading view
|
||||
forksList.remove(forksList.size() - 1);
|
||||
|
||||
List<Repository> result = response.body();
|
||||
assert result != null;
|
||||
|
||||
if (result.size() > 0) {
|
||||
pageSize = result.size();
|
||||
forksList.addAll(result);
|
||||
} else {
|
||||
adapter.setMoreDataAvailable(false);
|
||||
}
|
||||
|
||||
adapter.notifyDataChanged();
|
||||
activityRepoForksBinding.progressLoadMore.setVisibility(View.GONE);
|
||||
} else {
|
||||
Log.e(TAG, String.valueOf(response.code()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Repository>> call, @NonNull Throwable t) {
|
||||
Log.e(TAG, t.toString());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.search_menu, menu);
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
androidx.appcompat.widget.SearchView searchView =
|
||||
(androidx.appcompat.widget.SearchView) searchItem.getActionView();
|
||||
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
|
||||
searchView.setOnQueryTextListener(
|
||||
|
@ -207,27 +139,13 @@ public class RepoForksActivity extends BaseActivity {
|
|||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
filter(newText);
|
||||
return true;
|
||||
if (activityRepoForksBinding.recyclerView.getAdapter() != null) {
|
||||
adapter.getFilter().filter(newText);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private void filter(String text) {
|
||||
List<Repository> userRepositories = new ArrayList<>();
|
||||
|
||||
for (Repository d : forksList) {
|
||||
if (d.getOwner().getLogin().contains(text)
|
||||
|| d.getName().toLowerCase().contains(text)
|
||||
|| d.getDescription().toLowerCase().contains(text)) {
|
||||
|
||||
userRepositories.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
adapter.updateList(userRepositories);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,12 +8,15 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.mian.gitnex.R;
|
||||
|
@ -29,19 +32,62 @@ import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
|||
/**
|
||||
* @author M M Arif
|
||||
*/
|
||||
public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||
implements Filterable {
|
||||
|
||||
private final List<org.gitnex.tea4j.v2.models.Repository> forksListFull;
|
||||
private final Context context;
|
||||
private List<org.gitnex.tea4j.v2.models.Repository> forksList;
|
||||
private Runnable loadMoreListener;
|
||||
private boolean isLoading = false;
|
||||
private boolean isMoreDataAvailable = true;
|
||||
private OnLoadMoreListener loadMoreListener;
|
||||
private boolean isLoading = false, isMoreDataAvailable = true;
|
||||
|
||||
private final Filter forksFilter =
|
||||
new Filter() {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
List<org.gitnex.tea4j.v2.models.Repository> filteredList = new ArrayList<>();
|
||||
|
||||
if (constraint == null || constraint.length() == 0) {
|
||||
filteredList.addAll(forksListFull);
|
||||
} else {
|
||||
String filterPattern = constraint.toString().toLowerCase().trim();
|
||||
|
||||
for (org.gitnex.tea4j.v2.models.Repository item : forksListFull) {
|
||||
if (item.getFullName().toLowerCase().contains(filterPattern)
|
||||
|| item.getOwner()
|
||||
.getLogin()
|
||||
.toLowerCase()
|
||||
.contains(filterPattern)
|
||||
|| item.getOwner()
|
||||
.getEmail()
|
||||
.toLowerCase()
|
||||
.contains(filterPattern)) {
|
||||
filteredList.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FilterResults results = new FilterResults();
|
||||
results.values = filteredList;
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||
|
||||
forksList.clear();
|
||||
forksList.addAll((List) results.values);
|
||||
notifyDataChanged();
|
||||
}
|
||||
};
|
||||
|
||||
public RepoForksAdapter(
|
||||
Context ctx, List<org.gitnex.tea4j.v2.models.Repository> forksListMain) {
|
||||
|
||||
this.context = ctx;
|
||||
this.forksList = forksListMain;
|
||||
forksListFull = new ArrayList<>(forksList);
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
|
@ -59,7 +105,7 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
&& !isLoading
|
||||
&& loadMoreListener != null) {
|
||||
isLoading = true;
|
||||
loadMoreListener.run();
|
||||
loadMoreListener.onLoadMore();
|
||||
}
|
||||
((RepoForksAdapter.ForksHolder) holder).bindData(forksList.get(position));
|
||||
}
|
||||
|
@ -76,15 +122,19 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
|
||||
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
||||
isMoreDataAvailable = moreDataAvailable;
|
||||
if (!isMoreDataAvailable) {
|
||||
loadMoreListener.onLoadFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void notifyDataChanged() {
|
||||
notifyDataSetChanged();
|
||||
isLoading = false;
|
||||
loadMoreListener.onLoadFinished();
|
||||
}
|
||||
|
||||
public void setLoadMoreListener(Runnable loadMoreListener) {
|
||||
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
|
||||
this.loadMoreListener = loadMoreListener;
|
||||
}
|
||||
|
||||
|
@ -93,6 +143,18 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
notifyDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return forksFilter;
|
||||
}
|
||||
|
||||
public interface OnLoadMoreListener {
|
||||
|
||||
void onLoadMore();
|
||||
|
||||
void onLoadFinished();
|
||||
}
|
||||
|
||||
class ForksHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final ImageView image;
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package org.mian.gitnex.viewmodels;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import java.util.List;
|
||||
import org.gitnex.tea4j.v2.models.Repository;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.adapters.RepoForksAdapter;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* @author M M Arif
|
||||
*/
|
||||
public class RepositoryForksViewModel extends ViewModel {
|
||||
|
||||
private MutableLiveData<List<Repository>> forksList;
|
||||
private int resultLimit;
|
||||
|
||||
public LiveData<List<Repository>> getForksList(String repoOwner, String repoName, Context ctx) {
|
||||
|
||||
forksList = new MutableLiveData<>();
|
||||
resultLimit = Constants.getCurrentResultLimit(ctx);
|
||||
loadInitialList(repoOwner, repoName, ctx);
|
||||
return forksList;
|
||||
}
|
||||
|
||||
public void loadInitialList(String repoOwner, String repoName, Context ctx) {
|
||||
|
||||
Call<List<Repository>> call =
|
||||
RetrofitClient.getApiInterface(ctx).listForks(repoOwner, repoName, 1, resultLimit);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Repository>> call,
|
||||
@NonNull Response<List<Repository>> response) {
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
forksList.postValue(response.body());
|
||||
} else {
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericError));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Repository>> call, @NonNull Throwable t) {
|
||||
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadMore(
|
||||
String repoOwner, String repoName, int page, Context ctx, RepoForksAdapter adapter) {
|
||||
|
||||
Call<List<Repository>> call =
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
.listForks(repoOwner, repoName, page, resultLimit);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Repository>> call,
|
||||
@NonNull Response<List<Repository>> response) {
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
|
||||
List<Repository> list = forksList.getValue();
|
||||
assert list != null;
|
||||
assert response.body() != null;
|
||||
|
||||
if (response.body().size() != 0) {
|
||||
list.addAll(response.body());
|
||||
adapter.updateList(list);
|
||||
} else {
|
||||
adapter.setMoreDataAvailable(false);
|
||||
}
|
||||
} else {
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericError));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Repository>> call, @NonNull Throwable t) {
|
||||
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue