diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b5341d9e..dcfabf35 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,9 +39,6 @@ - diff --git a/app/src/main/java/org/mian/gitnex/activities/AdminUnadoptedReposActivity.java b/app/src/main/java/org/mian/gitnex/activities/AdminUnadoptedReposActivity.java deleted file mode 100644 index 16f5198d..00000000 --- a/app/src/main/java/org/mian/gitnex/activities/AdminUnadoptedReposActivity.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.mian.gitnex.activities; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.View; -import androidx.appcompat.widget.Toolbar; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; -import org.mian.gitnex.R; -import org.mian.gitnex.adapters.AdminUnadoptedReposAdapter; -import org.mian.gitnex.databinding.ActivityAdminCronTasksBinding; -import org.mian.gitnex.helpers.Constants; -import org.mian.gitnex.viewmodels.AdminUnadoptedReposViewModel; - -/** - * @author mmarif - * @author qwerty287 - */ -public class AdminUnadoptedReposActivity extends BaseActivity { - - private AdminUnadoptedReposViewModel viewModel; - private View.OnClickListener onClickListener; - private AdminUnadoptedReposAdapter adapter; - - private ActivityAdminCronTasksBinding binding; - - private int PAGE = 1; - private int resultLimit; - private boolean reload = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - - super.onCreate(savedInstanceState); - - binding = ActivityAdminCronTasksBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - viewModel = new ViewModelProvider(this).get(AdminUnadoptedReposViewModel.class); - - resultLimit = Constants.getCurrentResultLimit(ctx); - initCloseListener(); - binding.close.setOnClickListener(onClickListener); - - Toolbar toolbar = binding.toolbar; - setSupportActionBar(toolbar); - - binding.toolbarTitle.setText(R.string.unadoptedRepos); - - binding.recyclerView.setHasFixedSize(true); - binding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx)); - - binding.pullToRefresh.setOnRefreshListener( - () -> - new Handler(Looper.getMainLooper()) - .postDelayed( - () -> { - binding.pullToRefresh.setRefreshing(false); - PAGE = 1; - binding.progressBar.setVisibility(View.VISIBLE); - reload = true; - viewModel.loadRepos(ctx, PAGE, resultLimit, null); - }, - 500)); - - adapter = - new AdminUnadoptedReposAdapter( - new ArrayList<>(), - () -> { - PAGE = 1; - binding.progressBar.setVisibility(View.VISIBLE); - reload = true; - viewModel.loadRepos(ctx, PAGE, resultLimit, null); - }, - () -> { - PAGE += 1; - binding.progressBar.setVisibility(View.VISIBLE); - viewModel.loadRepos(ctx, PAGE, resultLimit, null); - }, - binding); - - binding.recyclerView.setAdapter(adapter); - - fetchDataAsync(ctx); - } - - private void fetchDataAsync(Context ctx) { - - AtomicInteger prevSize = new AtomicInteger(); - - viewModel - .getUnadoptedRepos(ctx, PAGE, resultLimit, null) - .observe( - this, - list -> { - binding.progressBar.setVisibility(View.GONE); - - boolean hasMore = reload || list.size() > prevSize.get(); - reload = false; - - prevSize.set(list.size()); - - if (list.size() > 0) { - adapter.updateList(list); - adapter.setHasMore(hasMore); - binding.noData.setVisibility(View.GONE); - } else { - binding.noData.setVisibility(View.VISIBLE); - } - }); - } - - private void initCloseListener() { - onClickListener = view -> finish(); - } -} diff --git a/app/src/main/java/org/mian/gitnex/activities/AdministrationActivity.java b/app/src/main/java/org/mian/gitnex/activities/AdministrationActivity.java index 6e8d97b2..efc74c92 100644 --- a/app/src/main/java/org/mian/gitnex/activities/AdministrationActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/AdministrationActivity.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.gitnex.tea4j.v2.models.Cron; import org.mian.gitnex.R; import org.mian.gitnex.adapters.AdminCronTasksAdapter; +import org.mian.gitnex.adapters.AdminUnadoptedReposAdapter; import org.mian.gitnex.api.models.settings.RepositoryGlobal; import org.mian.gitnex.databinding.ActivityAdministrationBinding; import org.mian.gitnex.databinding.BottomSheetGlobalRepositorySettingsBinding; @@ -86,10 +87,7 @@ public class AdministrationActivity extends BaseActivity { binding.cardCron.getRoot().setOnClickListener(v -> showCronTasksSheet()); - binding.cardUnadopted - .getRoot() - .setOnClickListener( - v -> startActivity(new Intent(this, AdminUnadoptedReposActivity.class))); + binding.cardUnadopted.getRoot().setOnClickListener(v -> showUnadoptedReposSheet()); binding.cardRepoSettings.getRoot().setOnClickListener(v -> showRepositorySettings()); } @@ -144,7 +142,7 @@ public class AdministrationActivity extends BaseActivity { }); viewModel - .getIsLoading() + .getIsCronLoading() .observe( this, loading -> @@ -211,7 +209,7 @@ public class AdministrationActivity extends BaseActivity { }); viewModel - .getIsLoading() + .getIsSettingsLoading() .observe( this, loading -> { @@ -248,6 +246,88 @@ public class AdministrationActivity extends BaseActivity { } } + private void showUnadoptedReposSheet() { + + BottomsheetAdminCronTasksBinding sheetBinding = + BottomsheetAdminCronTasksBinding.inflate(getLayoutInflater()); + BottomSheetDialog dialog = new BottomSheetDialog(this); + dialog.setContentView(sheetBinding.getRoot()); + AppUtil.applySheetStyle(dialog, true); + + sheetBinding.title.setText(R.string.unadoptedRepos); + viewModel.resetUnadoptedPagination(); + + AdminUnadoptedReposAdapter adapter = + new AdminUnadoptedReposAdapter(new ArrayList<>(), this::showUnadoptedActionDialog); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + sheetBinding.recyclerView.setLayoutManager(layoutManager); + sheetBinding.recyclerView.setAdapter(adapter); + + EndlessRecyclerViewScrollListener scrollListener = + new EndlessRecyclerViewScrollListener(layoutManager) { + @Override + public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { + viewModel.fetchUnadoptedRepos( + AdministrationActivity.this, page, resultLimit, false); + } + }; + sheetBinding.recyclerView.addOnScrollListener(scrollListener); + + viewModel + .getUnadoptedRepos() + .observe( + this, + list -> { + adapter.updateList(list); + sheetBinding + .layoutEmpty + .getRoot() + .setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE); + }); + + viewModel + .getIsUnadoptedLoading() + .observe( + this, + loading -> + sheetBinding.expressiveLoader.setVisibility( + loading ? View.VISIBLE : View.GONE)); + + viewModel + .getRepoActionSuccess() + .observe( + this, + result -> { + if (result != null) { + String message; + if (result.isDelete()) { + message = getString(R.string.repoDeletionSuccess); + } else { + message = getString(R.string.repoAdopted, result.repoName()); + } + Toasty.show(this, message); + } + }); + + viewModel.fetchUnadoptedRepos(this, 1, resultLimit, true); + dialog.show(); + } + + private void showUnadoptedActionDialog(String repoName) { + String[] parts = repoName.split("/"); + new MaterialAlertDialogBuilder(this) + .setTitle(repoName) + .setMessage(getString(R.string.unadoptedReposMessage, parts[1], parts[0])) + .setNeutralButton(R.string.close, null) + .setPositiveButton( + R.string.menuDeleteText, + (d, w) -> viewModel.performRepoAction(this, repoName, true)) + .setNegativeButton( + R.string.adoptRepo, + (d, w) -> viewModel.performRepoAction(this, repoName, false)) + .show(); + } + private void initCards() { binding.cardUsers.cardIcon.setImageResource(R.drawable.ic_people); binding.cardUsers.cardTitle.setText(R.string.adminUsers); diff --git a/app/src/main/java/org/mian/gitnex/adapters/AdminUnadoptedReposAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/AdminUnadoptedReposAdapter.java index a09edb00..8a7854f6 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/AdminUnadoptedReposAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/AdminUnadoptedReposAdapter.java @@ -1,169 +1,48 @@ 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.recyclerview.widget.RecyclerView; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.util.List; -import org.mian.gitnex.R; -import org.mian.gitnex.clients.RetrofitClient; -import org.mian.gitnex.databinding.ActivityAdminCronTasksBinding; -import org.mian.gitnex.helpers.AlertDialogs; -import org.mian.gitnex.helpers.Toasty; -import retrofit2.Call; -import retrofit2.Callback; +import org.mian.gitnex.databinding.ListAdminUnadoptedReposBinding; /** * @author mmarif * @author qwerty287 */ public class AdminUnadoptedReposAdapter - extends RecyclerView.Adapter { + extends RecyclerView.Adapter { - private final Runnable updateList; - private final Runnable loadMoreListener; - private final ActivityAdminCronTasksBinding activityAdminCronTasksBinding; - private List repos; - private boolean isLoading = false, hasMore = true; + private final List repos; + private final OnRepoClickListener listener; - public AdminUnadoptedReposAdapter( - List list, - Runnable updateList, - Runnable loadMore, - ActivityAdminCronTasksBinding activityAdminCronTasksBinding) { - this.repos = list; - this.updateList = updateList; - this.loadMoreListener = loadMore; - this.activityAdminCronTasksBinding = activityAdminCronTasksBinding; + public interface OnRepoClickListener { + void onRepoClick(String repoName); + } + + public AdminUnadoptedReposAdapter(List repos, OnRepoClickListener listener) { + this.repos = repos; + this.listener = listener; } @NonNull @Override - public UnadoptedViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - - View v = - LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_admin_unadopted_repos, parent, false); - return new UnadoptedViewHolder(v); + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + ListAdminUnadoptedReposBinding binding = + ListAdminUnadoptedReposBinding.inflate( + LayoutInflater.from(parent.getContext()), parent, false); + return new ViewHolder(binding); } @Override - public void onBindViewHolder(@NonNull UnadoptedViewHolder holder, int position) { - if (position >= getItemCount() - 1 && hasMore && !isLoading && loadMoreListener != null) { - isLoading = true; - loadMoreListener.run(); - } + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + String repo = repos.get(position); - String currentItem = repos.get(position); + holder.binding.repoName.setText(repo); + holder.binding.getRoot().setOnClickListener(v -> listener.onRepoClick(repo)); - holder.repoName = currentItem; - holder.name.setText(currentItem); - } - - private void updateAdapter(int position) { - repos.remove(position); - notifyItemRemoved(position); - notifyItemRangeChanged(position, repos.size()); - } - - private void delete(final Context ctx, final String name) { - - String[] repoSplit = name.split("/"); - - Call call = - RetrofitClient.getApiInterface(ctx) - .adminDeleteUnadoptedRepository(repoSplit[0], repoSplit[1]); - - call.enqueue( - new Callback<>() { - - @Override - public void onResponse( - @NonNull Call call, @NonNull retrofit2.Response response) { - - switch (response.code()) { - case 204: - updateList.run(); - Toasty.show(ctx, ctx.getString(R.string.repoDeletionSuccess)); - break; - - case 401: - AlertDialogs.authorizationTokenRevokedDialog(ctx); - break; - - case 403: - Toasty.show(ctx, ctx.getString(R.string.authorizeError)); - break; - - case 404: - Toasty.show(ctx, ctx.getString(R.string.apiNotFound)); - break; - - default: - Toasty.show(ctx, ctx.getString(R.string.genericError)); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - - Toasty.show(ctx, ctx.getString(R.string.genericServerResponseError)); - } - }); - } - - private void adopt(final Context ctx, final String name, int position) { - - String[] repoSplit = name.split("/"); - - Call call = - RetrofitClient.getApiInterface(ctx) - .adminAdoptRepository(repoSplit[0], repoSplit[1]); - - call.enqueue( - new Callback<>() { - - @Override - public void onResponse( - @NonNull Call call, @NonNull retrofit2.Response response) { - - switch (response.code()) { - case 204: - updateAdapter(position); - if (getItemCount() == 0) { - activityAdminCronTasksBinding.noData.setVisibility( - View.VISIBLE); - } - Toasty.show(ctx, ctx.getString(R.string.repoAdopted, name)); - break; - - case 401: - AlertDialogs.authorizationTokenRevokedDialog(ctx); - break; - - case 403: - Toasty.show(ctx, ctx.getString(R.string.authorizeError)); - break; - - case 404: - Toasty.show(ctx, ctx.getString(R.string.apiNotFound)); - break; - - default: - Toasty.show(ctx, ctx.getString(R.string.genericError)); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - - Toasty.show(ctx, ctx.getString(R.string.genericServerResponseError)); - } - }); + holder.binding.getRoot().updateAppearance(position, getItemCount()); } @Override @@ -172,54 +51,18 @@ public class AdminUnadoptedReposAdapter } @SuppressLint("NotifyDataSetChanged") - public void updateList(List list) { - this.repos = list; + public void updateList(List newList) { + this.repos.clear(); + this.repos.addAll(newList); notifyDataSetChanged(); } - public void setHasMore(boolean hasMore) { - this.hasMore = hasMore; - isLoading = false; - } + public static class ViewHolder extends RecyclerView.ViewHolder { + final ListAdminUnadoptedReposBinding binding; - public class UnadoptedViewHolder extends RecyclerView.ViewHolder { - - private final TextView name; - private String repoName; - - private UnadoptedViewHolder(View itemView) { - - super(itemView); - Context ctx = itemView.getContext(); - - name = itemView.findViewById(R.id.repo_name); - - itemView.setOnClickListener( - taskInfo -> { - String[] repoSplit = repoName.split("/"); - - MaterialAlertDialogBuilder materialAlertDialogBuilder = - new MaterialAlertDialogBuilder(ctx) - .setTitle(repoName) - .setMessage( - ctx.getString( - R.string.unadoptedReposMessage, - repoSplit[1], - repoSplit[0])) - .setNeutralButton(R.string.close, null) - .setPositiveButton( - R.string.menuDeleteText, - ((dialog, which) -> delete(ctx, repoName))) - .setNegativeButton( - R.string.adoptRepo, - ((dialog, which) -> - adopt( - ctx, - repoName, - getBindingAdapterPosition()))); - - materialAlertDialogBuilder.create().show(); - }); + ViewHolder(ListAdminUnadoptedReposBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/AdminUnadoptedReposViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AdminUnadoptedReposViewModel.java deleted file mode 100644 index a980fdc6..00000000 --- a/app/src/main/java/org/mian/gitnex/viewmodels/AdminUnadoptedReposViewModel.java +++ /dev/null @@ -1,78 +0,0 @@ -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.ArrayList; -import java.util.List; -import java.util.Objects; -import org.mian.gitnex.R; -import org.mian.gitnex.clients.RetrofitClient; -import org.mian.gitnex.helpers.AlertDialogs; -import org.mian.gitnex.helpers.Toasty; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -/** - * @author mmarif - * @author qwerty287 - */ -public class AdminUnadoptedReposViewModel extends ViewModel { - - private MutableLiveData> tasksList; - - public LiveData> getUnadoptedRepos( - Context ctx, int page, int limit, String query) { - - tasksList = new MutableLiveData<>(); - loadRepos(ctx, page, limit, query); - - return tasksList; - } - - public void loadRepos(final Context ctx, final int page, int limit, String query) { - - Call> call = - RetrofitClient.getApiInterface(ctx).adminUnadoptedList(page, limit, query); - - call.enqueue( - new Callback<>() { - - @Override - public void onResponse( - @NonNull Call> call, - @NonNull Response> response) { - - if (response.isSuccessful()) { - if (page <= 1 || tasksList.getValue() == null) { - tasksList.postValue(response.body()); - } else { - List repos = - new ArrayList<>( - Objects.requireNonNull(tasksList.getValue())); - assert response.body() != null; - repos.addAll(response.body()); - tasksList.postValue(repos); - } - } else if (response.code() == 401) { - AlertDialogs.authorizationTokenRevokedDialog(ctx); - } else if (response.code() == 403) { - Toasty.show(ctx, ctx.getString(R.string.authorizeError)); - } else if (response.code() == 404) { - Toasty.show(ctx, ctx.getString(R.string.apiNotFound)); - } else { - Toasty.show(ctx, ctx.getString(R.string.genericError)); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - - Toasty.show(ctx, ctx.getString(R.string.genericServerResponseError)); - } - }); - } -} diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/AdministrationViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AdministrationViewModel.java index 5f559fcc..a2947b45 100644 --- a/app/src/main/java/org/mian/gitnex/viewmodels/AdministrationViewModel.java +++ b/app/src/main/java/org/mian/gitnex/viewmodels/AdministrationViewModel.java @@ -23,12 +23,20 @@ public class AdministrationViewModel extends ViewModel { private final MutableLiveData repositorySettings = new MutableLiveData<>(); private final MutableLiveData> cronTasks = new MutableLiveData<>(new ArrayList<>()); - private final MutableLiveData isLoading = new MutableLiveData<>(false); + private final MutableLiveData> unadoptedRepos = + new MutableLiveData<>(new ArrayList<>()); + + private final MutableLiveData isSettingsLoading = new MutableLiveData<>(false); + private final MutableLiveData isCronLoading = new MutableLiveData<>(false); + private final MutableLiveData isUnadoptedLoading = new MutableLiveData<>(false); private final MutableLiveData errorMessage = new MutableLiveData<>(); private final MutableLiveData taskSuccessMessage = new MutableLiveData<>(); + private final MutableLiveData repoActionSuccess = new MutableLiveData<>(); private int cronTotalCount = -1; private boolean isCronLastPage = false; + private int unadoptedTotalCount = -1; + private boolean isUnadoptedLastPage = false; public LiveData getRepositorySettings() { return repositorySettings; @@ -38,8 +46,20 @@ public class AdministrationViewModel extends ViewModel { return cronTasks; } - public LiveData getIsLoading() { - return isLoading; + public LiveData> getUnadoptedRepos() { + return unadoptedRepos; + } + + public LiveData getIsSettingsLoading() { + return isSettingsLoading; + } + + public LiveData getIsCronLoading() { + return isCronLoading; + } + + public LiveData getIsUnadoptedLoading() { + return isUnadoptedLoading; } public LiveData getErrorMessage() { @@ -50,8 +70,12 @@ public class AdministrationViewModel extends ViewModel { return taskSuccessMessage; } + public LiveData getRepoActionSuccess() { + return repoActionSuccess; + } + public void fetchRepositoryGlobalSettings(Context context) { - isLoading.setValue(true); + isSettingsLoading.setValue(true); ApiRetrofitClient.getInstance(context) .getRepositoryGlobalSettings() .enqueue( @@ -60,29 +84,26 @@ public class AdministrationViewModel extends ViewModel { public void onResponse( @NonNull Call call, @NonNull Response response) { - isLoading.setValue(false); - if (response.isSuccessful()) { + isSettingsLoading.setValue(false); + if (response.isSuccessful()) repositorySettings.setValue(response.body()); - } else { - errorMessage.setValue("Error: " + response.code()); - } + else errorMessage.setValue("Error: " + response.code()); } @Override public void onFailure( @NonNull Call call, @NonNull Throwable t) { - isLoading.setValue(false); + isSettingsLoading.setValue(false); errorMessage.setValue(t.getMessage()); } }); } public void fetchCronTasks(Context context, int page, int limit, boolean isRefresh) { - if (Boolean.TRUE.equals(isLoading.getValue())) return; + if (Boolean.TRUE.equals(isCronLoading.getValue())) return; if (!isRefresh && isCronLastPage) return; - isLoading.setValue(true); - + isCronLoading.setValue(true); RetrofitClient.getApiInterface(context) .adminCronList(page, limit) .enqueue( @@ -91,69 +112,155 @@ public class AdministrationViewModel extends ViewModel { public void onResponse( @NonNull Call> call, @NonNull Response> response) { - isLoading.setValue(false); + isCronLoading.setValue(false); if (response.isSuccessful() && response.body() != null) { - String totalHeader = response.headers().get("x-total-count"); - if (totalHeader != null) { - cronTotalCount = Integer.parseInt(totalHeader); - } - - List currentList = - isRefresh - ? new ArrayList<>() - : new ArrayList<>( - Objects.requireNonNull( - cronTasks.getValue())); - currentList.addAll(response.body()); - cronTasks.setValue(currentList); - - if (response.body().size() < limit - || currentList.size() >= cronTotalCount) { - isCronLastPage = true; - } - } else { - errorMessage.setValue("Error: " + response.code()); - } + handleCronResponse( + response.body(), + response.headers().get("x-total-count"), + limit, + isRefresh); + } else errorMessage.setValue("Error: " + response.code()); } @Override public void onFailure( @NonNull Call> call, @NonNull Throwable t) { - isLoading.setValue(false); + isCronLoading.setValue(false); errorMessage.setValue(t.getMessage()); } }); } + private void handleCronResponse( + List body, String totalHeader, int limit, boolean isRefresh) { + if (totalHeader != null) cronTotalCount = Integer.parseInt(totalHeader); + List currentList = + isRefresh + ? new ArrayList<>() + : new ArrayList<>(Objects.requireNonNull(cronTasks.getValue())); + currentList.addAll(body); + cronTasks.setValue(currentList); + if (body.size() < limit || currentList.size() >= cronTotalCount) isCronLastPage = true; + } + + public void runCronTask(Context context, String taskName) { + isCronLoading.setValue(true); + RetrofitClient.getApiInterface(context) + .adminCronRun(taskName) + .enqueue( + new Callback<>() { + @Override + public void onResponse( + @NonNull Call call, @NonNull Response response) { + isCronLoading.setValue(false); + if (response.code() == 204) { + taskSuccessMessage.setValue(taskName); + taskSuccessMessage.setValue(null); + } else errorMessage.setValue("Error: " + response.code()); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + isCronLoading.setValue(false); + errorMessage.setValue(t.getMessage()); + } + }); + } + + public void fetchUnadoptedRepos(Context context, int page, int limit, boolean isRefresh) { + if (Boolean.TRUE.equals(isUnadoptedLoading.getValue())) return; + if (!isRefresh && isUnadoptedLastPage) return; + + isUnadoptedLoading.setValue(true); + RetrofitClient.getApiInterface(context) + .adminUnadoptedList(page, limit, null) + .enqueue( + new Callback<>() { + @Override + public void onResponse( + @NonNull Call> call, + @NonNull Response> response) { + isUnadoptedLoading.setValue(false); + if (response.isSuccessful() && response.body() != null) { + handleUnadoptedResponse( + response.body(), + response.headers().get("x-total-count"), + limit, + isRefresh); + } else errorMessage.setValue("Error: " + response.code()); + } + + @Override + public void onFailure( + @NonNull Call> call, @NonNull Throwable t) { + isUnadoptedLoading.setValue(false); + errorMessage.setValue(t.getMessage()); + } + }); + } + + private void handleUnadoptedResponse( + List body, String totalHeader, int limit, boolean isRefresh) { + if (totalHeader != null) unadoptedTotalCount = Integer.parseInt(totalHeader); + List currentList = + isRefresh + ? new ArrayList<>() + : new ArrayList<>(Objects.requireNonNull(unadoptedRepos.getValue())); + currentList.addAll(body); + unadoptedRepos.setValue(currentList); + if (body.size() < limit || currentList.size() >= unadoptedTotalCount) + isUnadoptedLastPage = true; + } + + public void performRepoAction(Context context, String repoName, boolean isDelete) { + isUnadoptedLoading.setValue(true); + String[] parts = repoName.split("/"); + Call call = + isDelete + ? RetrofitClient.getApiInterface(context) + .adminDeleteUnadoptedRepository(parts[0], parts[1]) + : RetrofitClient.getApiInterface(context) + .adminAdoptRepository(parts[0], parts[1]); + + call.enqueue( + new Callback<>() { + @Override + public void onResponse( + @NonNull Call call, @NonNull Response response) { + isUnadoptedLoading.setValue(false); + if (response.code() == 204) { + List current = + new ArrayList<>( + Objects.requireNonNull(unadoptedRepos.getValue())); + current.remove(repoName); + unadoptedRepos.setValue(current); + + repoActionSuccess.setValue(new RepoActionResult(repoName, isDelete)); + repoActionSuccess.setValue(null); + } else { + errorMessage.setValue("Error: " + response.code()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + isUnadoptedLoading.setValue(false); + errorMessage.setValue(t.getMessage()); + } + }); + } + public void resetCronPagination() { this.isCronLastPage = false; this.cronTotalCount = -1; this.cronTasks.setValue(new ArrayList<>()); } - public void runCronTask(Context context, String taskName) { - isLoading.setValue(true); - RetrofitClient.getApiInterface(context) - .adminCronRun(taskName) - .enqueue( - new Callback<>() { - @Override - public void onResponse( - @NonNull Call call, @NonNull Response response) { - isLoading.setValue(false); - if (response.code() == 204) { - taskSuccessMessage.setValue(taskName); - taskSuccessMessage.setValue(null); - } else { - errorMessage.setValue("Error: " + response.code()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - isLoading.setValue(false); - errorMessage.setValue(t.getMessage()); - } - }); + public void resetUnadoptedPagination() { + this.isUnadoptedLastPage = false; + this.unadoptedTotalCount = -1; + this.unadoptedRepos.setValue(new ArrayList<>()); } + + public record RepoActionResult(String repoName, boolean isDelete) {} } diff --git a/app/src/main/res/layout/activity_admin_cron_tasks.xml b/app/src/main/res/layout/activity_admin_cron_tasks.xml deleted file mode 100644 index ef4e99ba..00000000 --- a/app/src/main/res/layout/activity_admin_cron_tasks.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml b/app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml index 61fb7473..a8ab4527 100644 --- a/app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml +++ b/app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml @@ -23,14 +23,28 @@ + + - + android:layout_width="match_parent" + android:layout_height="wrap_content"> - + android:checkable="false" + android:layout_marginVertical="@dimen/dimen1dp" + app:strokeWidth="0dp" + app:cardBackgroundColor="?attr/materialCardBackgroundColor"> - + android:padding="@dimen/dimen8dp" + android:textColor="?attr/primaryTextColor" /> - + - - - - - +