mirror of
https://github.com/gitnex-org/gitnex.git
synced 2026-03-26 08:18:03 -05:00
Improve branches UI and add pagination to it
This commit is contained in:
@@ -29,7 +29,6 @@ import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.gitnex.tea4j.v2.models.Branch;
|
||||
import org.gitnex.tea4j.v2.models.Milestone;
|
||||
import org.gitnex.tea4j.v2.models.Organization;
|
||||
import org.gitnex.tea4j.v2.models.Repository;
|
||||
@@ -247,9 +246,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
||||
public void onButtonClicked(String text) {
|
||||
|
||||
switch (text) {
|
||||
case "chooseBranch":
|
||||
chooseBranch();
|
||||
break;
|
||||
case "openWebRepo":
|
||||
AppUtil.openUrlInBrowser(this, repository.getRepository().getHtmlUrl());
|
||||
break;
|
||||
@@ -418,68 +414,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
||||
}
|
||||
}
|
||||
|
||||
private void chooseBranch() {
|
||||
|
||||
progressDialog = new Dialog(this);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setContentView(R.layout.custom_progress_loader);
|
||||
progressDialog.show();
|
||||
|
||||
Call<List<Branch>> call =
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
.repoListBranches(repository.getOwner(), repository.getName(), null, null);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Branch>> call,
|
||||
@NonNull Response<List<Branch>> response) {
|
||||
|
||||
progressDialog.hide();
|
||||
if (response.code() == 200) {
|
||||
|
||||
List<String> branchesList = new ArrayList<>();
|
||||
int selectedBranch = 0;
|
||||
assert response.body() != null;
|
||||
|
||||
for (int i = 0; i < response.body().size(); i++) {
|
||||
|
||||
Branch branches = response.body().get(i);
|
||||
branchesList.add(branches.getName());
|
||||
|
||||
if (repository.getBranchRef().equals(branches.getName())) {
|
||||
selectedBranch = i;
|
||||
}
|
||||
}
|
||||
|
||||
materialAlertDialogBuilder
|
||||
.setTitle(R.string.pageTitleChooseBranch)
|
||||
.setSingleChoiceItems(
|
||||
branchesList.toArray(new String[0]),
|
||||
selectedBranch,
|
||||
(dialogInterface, i) -> {
|
||||
repository.setBranchRef(branchesList.get(i));
|
||||
|
||||
if (getFragmentRefreshListenerFiles() != null) {
|
||||
getFragmentRefreshListenerFiles()
|
||||
.onRefresh(branchesList.get(i));
|
||||
}
|
||||
dialogInterface.dismiss();
|
||||
})
|
||||
.setNeutralButton(R.string.cancelButton, null);
|
||||
materialAlertDialogBuilder.create().show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
|
||||
progressDialog.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getRepoInfo(final String owner, String repo) {
|
||||
|
||||
LinearProgressIndicator loading = findViewById(R.id.loadingIndicator);
|
||||
@@ -670,18 +604,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
||||
mainIntent.removeExtra("goToSectionType");
|
||||
|
||||
switch (Objects.requireNonNull(goToSectionType)) {
|
||||
case "branchesList":
|
||||
viewPager.setCurrentItem(1);
|
||||
chooseBranch();
|
||||
break;
|
||||
case "branch":
|
||||
viewPager.setCurrentItem(1);
|
||||
String selectedBranch = mainIntent.getStringExtra("selectedBranch");
|
||||
repository.setBranchRef(selectedBranch);
|
||||
if (getFragmentRefreshListenerFiles() != null) {
|
||||
getFragmentRefreshListenerFiles().onRefresh(selectedBranch);
|
||||
}
|
||||
break;
|
||||
case "file":
|
||||
viewPager.setCurrentItem(1);
|
||||
String branch1 = mainIntent.getStringExtra("branch");
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.mian.gitnex.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.gitnex.tea4j.v2.models.Branch;
|
||||
import org.mian.gitnex.R;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class BranchAdapter extends RecyclerView.Adapter<BranchAdapter.BranchViewHolder> {
|
||||
|
||||
private final List<Branch> branches = new ArrayList<>();
|
||||
private final OnBranchClickListener listener;
|
||||
|
||||
public interface OnBranchClickListener {
|
||||
void onBranchClick(String branchName);
|
||||
}
|
||||
|
||||
public BranchAdapter(OnBranchClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public BranchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view =
|
||||
LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_branches, parent, false);
|
||||
return new BranchViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return branches.size();
|
||||
}
|
||||
|
||||
public void addBranches(List<Branch> newBranches) {
|
||||
int startPosition = branches.size();
|
||||
branches.addAll(newBranches);
|
||||
notifyItemRangeInserted(startPosition, newBranches.size());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
int oldSize = branches.size();
|
||||
branches.clear();
|
||||
notifyItemRangeRemoved(0, oldSize);
|
||||
}
|
||||
|
||||
public static class BranchViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView textView;
|
||||
|
||||
BranchViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
textView = itemView.findViewById(R.id.branch_name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(BranchViewHolder holder, int position) {
|
||||
|
||||
Branch branch = branches.get(position);
|
||||
holder.textView.setText(branch.getName());
|
||||
holder.textView.setOnClickListener(
|
||||
v -> {
|
||||
if (listener != null) {
|
||||
listener.onBranchClick(branch.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -14,12 +15,14 @@ import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.view.MenuProvider;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -33,6 +36,7 @@ import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.activities.CreateFileActivity;
|
||||
import org.mian.gitnex.activities.FileViewActivity;
|
||||
import org.mian.gitnex.activities.RepoDetailActivity;
|
||||
import org.mian.gitnex.adapters.BranchAdapter;
|
||||
import org.mian.gitnex.adapters.FilesAdapter;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.database.api.BaseApi;
|
||||
@@ -40,6 +44,7 @@ import org.mian.gitnex.database.api.UserAccountsApi;
|
||||
import org.mian.gitnex.database.models.UserAccount;
|
||||
import org.mian.gitnex.databinding.FragmentFilesBinding;
|
||||
import org.mian.gitnex.helpers.AppUtil;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.Path;
|
||||
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||
import org.mian.gitnex.viewmodels.FilesViewModel;
|
||||
@@ -405,60 +410,146 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
|
||||
progressDialog.setContentView(R.layout.custom_progress_loader);
|
||||
progressDialog.show();
|
||||
|
||||
MaterialAlertDialogBuilder materialAlertDialogBuilder =
|
||||
new MaterialAlertDialogBuilder(
|
||||
requireContext(), R.style.ThemeOverlay_Material3_Dialog_Alert);
|
||||
MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(requireContext());
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.custom_branches_dialog, null);
|
||||
dialogBuilder.setView(dialogView);
|
||||
|
||||
Call<List<Branch>> call =
|
||||
RetrofitClient.getApiInterface(requireContext())
|
||||
.repoListBranches(repository.getOwner(), repository.getName(), null, null);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
RecyclerView recyclerView = dialogView.findViewById(R.id.recyclerView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
|
||||
recyclerView.addItemDecoration(
|
||||
new RecyclerView.ItemDecoration() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Branch>> call,
|
||||
@NonNull Response<List<Branch>> response) {
|
||||
public void getItemOffsets(
|
||||
@NonNull Rect outRect,
|
||||
@NonNull View view,
|
||||
@NonNull RecyclerView parent,
|
||||
@NonNull RecyclerView.State state) {
|
||||
|
||||
progressDialog.hide();
|
||||
if (response.code() == 200) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int spacing =
|
||||
(int)
|
||||
requireContext()
|
||||
.getResources()
|
||||
.getDimension(R.dimen.dimen20dp);
|
||||
|
||||
List<String> branchesList = new ArrayList<>();
|
||||
int selectedBranch = 0;
|
||||
assert response.body() != null;
|
||||
outRect.right = spacing;
|
||||
outRect.left = spacing;
|
||||
|
||||
for (int i = 0; i < response.body().size(); i++) {
|
||||
|
||||
Branch branches = response.body().get(i);
|
||||
branchesList.add(branches.getName());
|
||||
|
||||
if (repository.getBranchRef().equals(branches.getName())) {
|
||||
selectedBranch = i;
|
||||
}
|
||||
}
|
||||
|
||||
materialAlertDialogBuilder
|
||||
.setTitle(R.string.pageTitleChooseBranch)
|
||||
.setSingleChoiceItems(
|
||||
branchesList.toArray(new String[0]),
|
||||
selectedBranch,
|
||||
(dialogInterface, i) -> {
|
||||
repository.setBranchRef(branchesList.get(i));
|
||||
binding.branchTitle.setText(branchesList.get(i));
|
||||
|
||||
refresh();
|
||||
dialogInterface.dismiss();
|
||||
})
|
||||
.setNeutralButton(R.string.cancelButton, null);
|
||||
materialAlertDialogBuilder.create().show();
|
||||
if (position > 0) {
|
||||
outRect.top = spacing;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialogBuilder.setNeutralButton(R.string.close, (dialog, which) -> dialog.dismiss());
|
||||
AlertDialog dialog = dialogBuilder.create();
|
||||
dialog.setCancelable(false);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
|
||||
final int[] page = {1};
|
||||
final int resultLimit = Constants.getCurrentResultLimit(requireContext());
|
||||
final boolean[] isLoading = {false};
|
||||
final boolean[] isLastPage = {false};
|
||||
|
||||
BranchAdapter adapter =
|
||||
new BranchAdapter(
|
||||
branchName -> {
|
||||
repository.setBranchRef(branchName);
|
||||
binding.branchTitle.setText(branchName);
|
||||
refresh();
|
||||
dialog.dismiss();
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
Runnable fetchBranches =
|
||||
() -> {
|
||||
if (isLoading[0] || isLastPage[0]) return;
|
||||
isLoading[0] = true;
|
||||
|
||||
Call<List<Branch>> call =
|
||||
RetrofitClient.getApiInterface(requireContext())
|
||||
.repoListBranches(
|
||||
repository.getOwner(),
|
||||
repository.getName(),
|
||||
page[0],
|
||||
resultLimit);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Branch>> call,
|
||||
@NonNull Response<List<Branch>> response) {
|
||||
|
||||
isLoading[0] = false;
|
||||
|
||||
if (response.code() == 200 && response.body() != null) {
|
||||
List<Branch> newBranches = response.body();
|
||||
adapter.addBranches(newBranches);
|
||||
|
||||
String totalCountStr =
|
||||
response.headers().get("X-Total-Count");
|
||||
|
||||
if (totalCountStr != null) {
|
||||
|
||||
int totalItems = Integer.parseInt(totalCountStr);
|
||||
int totalPages =
|
||||
(int)
|
||||
Math.ceil(
|
||||
(double) totalItems
|
||||
/ resultLimit);
|
||||
isLastPage[0] = page[0] >= totalPages;
|
||||
} else {
|
||||
isLastPage[0] = newBranches.size() < resultLimit;
|
||||
}
|
||||
page[0]++;
|
||||
|
||||
if (page[0] == 2 && !dialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
dialog.show();
|
||||
}
|
||||
} else {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
|
||||
isLoading[0] = false;
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
recyclerView.addOnScrollListener(
|
||||
new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
|
||||
progressDialog.hide();
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
LinearLayoutManager layoutManager =
|
||||
(LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
|
||||
if (layoutManager != null) {
|
||||
|
||||
int visibleItemCount = layoutManager.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
int firstVisibleItemPosition =
|
||||
layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if (!isLoading[0]
|
||||
&& !isLastPage[0]
|
||||
&& (visibleItemCount + firstVisibleItemPosition)
|
||||
>= totalItemCount - 5) {
|
||||
fetchBranches.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
adapter.clear();
|
||||
fetchBranches.run();
|
||||
}
|
||||
}
|
||||
|
||||
23
app/src/main/res/layout/custom_branches_dialog.xml
Normal file
23
app/src/main/res/layout/custom_branches_dialog.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pageTitleChooseBranch"
|
||||
android:textAppearance="?attr/textAppearanceHeadline5"
|
||||
android:layout_marginBottom="@dimen/dimen8dp"
|
||||
android:padding="@dimen/dimen16dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dimen320dp"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
7
app/src/main/res/layout/list_branches.xml
Normal file
7
app/src/main/res/layout/list_branches.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/branch_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
@@ -55,7 +55,7 @@
|
||||
android:paddingEnd="@dimen/dimen2dp"
|
||||
android:text="@string/userName"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="14sp"/>
|
||||
android:textSize="@dimen/dimen14sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/userName"
|
||||
|
||||
Reference in New Issue
Block a user