GitNex-Android-App/app/src/main/java/org/mian/gitnex/adapters/TagsAdapter.java

224 lines
7.5 KiB
Java
Raw Normal View History

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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.gitnex.tea4j.v2.models.Tag;
import org.mian.gitnex.R;
Don't use TinyDB as cache (#1034) Do not use TinyDB as a cache or a way to send data between activities. ### How is this working Instead of saving everything into the TinyDB, I created three `Context`s (a `RepositoryContext`, an `IssueContext` and an `AccountContext`). All are used to store things like API or database values/models and additional data, e.g. the `RepositoryContext` also contains information about the current filter state of a repository (issues, pull requests, releases/tags and milestones). These are sent using `Intent`s and `Bundle`s between activities and fragments. Changing a field (e.g. filter state) in any fragment changes it also for the whole repository (or at least it should do so). Due to the size of the changes (after https://codeberg.org/gitnex/GitNex/commit/c9172f85efafd9f25739fdd8385e1904b711ea41, Git says `154 files changed, 3318 insertions(+), 3835 deletions(-)`) **I highly recommend you to create a beta/pre release before releasing a stable version**. Additional changes: * after logging out, the account remains in the account list (with a note) and you can log in again (you can't switch to this account) * repositories and organizations are clickable on user profiles * deleted two unused classes Once finished, hopefully * closes #354 * replaces #897 * fixes #947 * closes #1001 * closes #1015 * marks #876 and #578 as `Wontfix` since they are not necessary at this point * and all the other TinyDB issues Co-authored-by: qwerty287 <ndev@web.de> Co-authored-by: M M Arif <mmarif@noreply.codeberg.org> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1034 Reviewed-by: 6543 <6543@noreply.codeberg.org> Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org> Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2022-03-13 03:59:13 +01:00
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentReleasesBinding;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.structs.FragmentRefreshListener;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* @author qwerty287
*/
public class TagsAdapter extends RecyclerView.Adapter<TagsAdapter.TagsViewHolder> {
private List<Tag> tags;
private final Context context;
private final String repo;
private final String owner;
private final FragmentRefreshListener startDownload;
private final FragmentReleasesBinding fragmentReleasesBinding;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
protected class TagsViewHolder extends RecyclerView.ViewHolder {
private Tag tagsHolder;
private final TextView tagName;
private final TextView tagBody;
private final LinearLayout downloadCopyFrame;
private final LinearLayout downloads;
private final LinearLayout releaseZipDownloadFrame;
private final LinearLayout releaseTarDownloadFrame;
private final ImageView downloadDropdownIcon;
private final ImageView options;
private TagsViewHolder(View itemView) {
super(itemView);
tagName = itemView.findViewById(R.id.tagName);
tagBody = itemView.findViewById(R.id.tagBodyContent);
downloadCopyFrame = itemView.findViewById(R.id.downloadCopyFrame);
downloads = itemView.findViewById(R.id.downloads);
releaseZipDownloadFrame = itemView.findViewById(R.id.releaseZipDownloadFrame);
releaseTarDownloadFrame = itemView.findViewById(R.id.releaseTarDownloadFrame);
downloadDropdownIcon = itemView.findViewById(R.id.downloadDropdownIcon);
options = itemView.findViewById(R.id.tagsOptionsMenu);
options.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams")
View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_tag_in_list, null);
TextView delete = view.findViewById(R.id.tagMenuDelete);
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
delete.setOnClickListener(v1 -> {
tagDeleteDialog(context, tagsHolder.getName(), owner, repo, getBindingAdapterPosition());
dialog.dismiss();
});
});
}
}
public TagsAdapter(Context ctx, List<Tag> releasesMain, String repoOwner, String repoName, FragmentRefreshListener startDownload, FragmentReleasesBinding fragmentReleasesBinding) {
this.context = ctx;
this.tags = releasesMain;
owner = repoOwner;
repo = repoName;
this.startDownload = startDownload;
this.fragmentReleasesBinding = fragmentReleasesBinding;
}
@NonNull
@Override
public TagsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_tags, parent, false);
return new TagsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull TagsViewHolder holder, int position) {
Tag currentItem = tags.get(position);
holder.tagsHolder = currentItem;
holder.tagName.setText(currentItem.getName());
if(!currentItem.getMessage().equals("")) {
Markdown.render(context, currentItem.getMessage(), holder.tagBody);
}
else {
holder.tagBody.setVisibility(View.GONE);
}
holder.downloadCopyFrame.setOnClickListener(v -> {
if(holder.downloads.getVisibility() == View.GONE) {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_down);
holder.downloads.setVisibility(View.VISIBLE);
}
else {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_right);
holder.downloads.setVisibility(View.GONE);
}
});
if(!((RepoDetailActivity) context).repository.getPermissions().isPush()) {
holder.options.setVisibility(View.GONE);
}
holder.releaseZipDownloadFrame.setOnClickListener(v -> startDownload.onRefresh(currentItem.getZipballUrl()));
holder.releaseTarDownloadFrame.setOnClickListener(v -> startDownload.onRefresh(currentItem.getTarballUrl()));
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
}
@Override
public int getItemCount() {
return tags.size();
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
if(!isMoreDataAvailable) {
loadMoreListener.onLoadFinished();
}
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
loadMoreListener.onLoadFinished();
}
public interface OnLoadMoreListener {
void onLoadMore();
void onLoadFinished();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Tag> list) {
tags = list;
notifyDataChanged();
}
private void updateAdapter(int position) {
tags.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, tags.size());
}
private void tagDeleteDialog(final Context context, final String tagName, final String owner, final String repo, int position) {
new AlertDialog.Builder(context)
.setTitle(String.format(context.getString(R.string.deleteGenericTitle), tagName))
.setMessage(R.string.deleteTagConfirmation)
.setIcon(R.drawable.ic_delete)
.setPositiveButton(R.string.menuDeleteText, (dialog, whichButton) -> RetrofitClient
.getApiInterface(context).repoDeleteTag(owner, repo, tagName).enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
if(response.isSuccessful()) {
updateAdapter(position);
Toasty.success(context, context.getString(R.string.tagDeleted));
if(getItemCount() == 0) {
fragmentReleasesBinding.noDataReleases.setVisibility(View.VISIBLE);
}
}
else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 409) {
Toasty.error(context, context.getString(R.string.tagDeleteError));
}
else {
Toasty.error(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.error(context, context.getString(R.string.genericError));
}
}))
.setNeutralButton(R.string.cancelButton, null).show();
}
}