mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2024-12-16 15:48:13 +08:00
Add support for tags (#1002)
Closes #983 TODO - [x] create tags - [x] view tags - [x] apply pagination - [x] delete tags Co-authored-by: qwerty287 <ndev@web.de> Co-authored-by: M M Arif <mmarif@noreply.codeberg.org> Co-authored-by: M M Arif <mmarif@swatian.com> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1002 Reviewed-by: M M Arif <mmarif@noreply.codeberg.org> Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org> Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
This commit is contained in:
parent
8cfd4b6a31
commit
f79d227bff
@ -109,7 +109,7 @@ dependencies {
|
|||||||
implementation "androidx.work:work-runtime:$work_version"
|
implementation "androidx.work:work-runtime:$work_version"
|
||||||
implementation "io.mikael:urlbuilder:2.0.9"
|
implementation "io.mikael:urlbuilder:2.0.9"
|
||||||
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
|
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
|
||||||
implementation "org.codeberg.gitnex:tea4j:1.0.29"
|
implementation "org.codeberg.gitnex:tea4j:1.0.30"
|
||||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||||
implementation 'androidx.biometric:biometric:1.1.0'
|
implementation 'androidx.biometric:biometric:1.1.0'
|
||||||
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
||||||
|
@ -15,6 +15,8 @@ import android.widget.EditText;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import org.gitnex.tea4j.models.Branches;
|
import org.gitnex.tea4j.models.Branches;
|
||||||
|
import org.gitnex.tea4j.models.CreateTagOptions;
|
||||||
|
import org.gitnex.tea4j.models.GitTag;
|
||||||
import org.gitnex.tea4j.models.Releases;
|
import org.gitnex.tea4j.models.Releases;
|
||||||
import org.mian.gitnex.R;
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
@ -44,6 +46,7 @@ public class CreateReleaseActivity extends BaseActivity {
|
|||||||
private CheckBox releaseDraft;
|
private CheckBox releaseDraft;
|
||||||
private Button createNewRelease;
|
private Button createNewRelease;
|
||||||
private String selectedBranch;
|
private String selectedBranch;
|
||||||
|
private Button createNewTag;
|
||||||
|
|
||||||
private String repoOwner;
|
private String repoOwner;
|
||||||
private String repoName;
|
private String repoName;
|
||||||
@ -97,6 +100,7 @@ public class CreateReleaseActivity extends BaseActivity {
|
|||||||
getBranches(Authorization.get(ctx), repoOwner, repoName);
|
getBranches(Authorization.get(ctx), repoOwner, repoName);
|
||||||
|
|
||||||
createNewRelease = activityCreateReleaseBinding.createNewRelease;
|
createNewRelease = activityCreateReleaseBinding.createNewRelease;
|
||||||
|
createNewTag = activityCreateReleaseBinding.createNewTag;
|
||||||
disableProcessButton();
|
disableProcessButton();
|
||||||
|
|
||||||
if(!connToInternet) {
|
if(!connToInternet) {
|
||||||
@ -108,6 +112,79 @@ public class CreateReleaseActivity extends BaseActivity {
|
|||||||
createNewRelease.setOnClickListener(createReleaseListener);
|
createNewRelease.setOnClickListener(createReleaseListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createNewTag.setOnClickListener(v -> createNewTag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNewTag() {
|
||||||
|
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
|
||||||
|
|
||||||
|
String tagName = releaseTagName.getText().toString();
|
||||||
|
String message = releaseTitle.getText().toString() + "\n\n" + releaseContent.getText().toString();
|
||||||
|
|
||||||
|
if(!connToInternet) {
|
||||||
|
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tagName.equals("")) {
|
||||||
|
Toasty.error(ctx, getString(R.string.tagNameErrorEmpty));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selectedBranch == null) {
|
||||||
|
Toasty.error(ctx, getString(R.string.selectBranchError));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
disableProcessButton();
|
||||||
|
|
||||||
|
CreateTagOptions createReleaseJson = new CreateTagOptions(message, tagName, selectedBranch);
|
||||||
|
|
||||||
|
Call<GitTag> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.createTag(Authorization.get(ctx), repoOwner, repoName, createReleaseJson);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<GitTag>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<GitTag> call, @NonNull retrofit2.Response<GitTag> response) {
|
||||||
|
|
||||||
|
if (response.code() == 201) {
|
||||||
|
tinyDB.putBoolean("updateReleases", true);
|
||||||
|
Toasty.success(ctx, getString(R.string.tagCreated));
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
else if(response.code() == 401) {
|
||||||
|
enableProcessButton();
|
||||||
|
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
|
||||||
|
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
|
||||||
|
ctx.getResources().getString(R.string.cancelButton),
|
||||||
|
ctx.getResources().getString(R.string.navLogout));
|
||||||
|
}
|
||||||
|
else if(response.code() == 403) {
|
||||||
|
enableProcessButton();
|
||||||
|
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
|
||||||
|
}
|
||||||
|
else if(response.code() == 404) {
|
||||||
|
enableProcessButton();
|
||||||
|
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enableProcessButton();
|
||||||
|
Toasty.error(ctx, ctx.getString(R.string.genericError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<GitTag> call, @NonNull Throwable t) {
|
||||||
|
Log.e("onFailure", t.toString());
|
||||||
|
enableProcessButton();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final View.OnClickListener createReleaseListener = v -> processNewRelease();
|
private final View.OnClickListener createReleaseListener = v -> processNewRelease();
|
||||||
@ -268,12 +345,12 @@ public class CreateReleaseActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void disableProcessButton() {
|
private void disableProcessButton() {
|
||||||
|
createNewTag.setEnabled(false);
|
||||||
createNewRelease.setEnabled(false);
|
createNewRelease.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableProcessButton() {
|
private void enableProcessButton() {
|
||||||
|
createNewTag.setEnabled(true);
|
||||||
createNewRelease.setEnabled(true);
|
createNewRelease.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ import org.mian.gitnex.database.models.UserAccount;
|
|||||||
import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
|
import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
|
||||||
import org.mian.gitnex.fragments.BottomSheetMilestonesFilterFragment;
|
import org.mian.gitnex.fragments.BottomSheetMilestonesFilterFragment;
|
||||||
import org.mian.gitnex.fragments.BottomSheetPullRequestFilterFragment;
|
import org.mian.gitnex.fragments.BottomSheetPullRequestFilterFragment;
|
||||||
|
import org.mian.gitnex.fragments.BottomSheetReleasesTagsFragment;
|
||||||
import org.mian.gitnex.fragments.BottomSheetRepoFragment;
|
import org.mian.gitnex.fragments.BottomSheetRepoFragment;
|
||||||
import org.mian.gitnex.fragments.CollaboratorsFragment;
|
import org.mian.gitnex.fragments.CollaboratorsFragment;
|
||||||
import org.mian.gitnex.fragments.FilesFragment;
|
import org.mian.gitnex.fragments.FilesFragment;
|
||||||
@ -76,6 +77,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
|||||||
private FragmentRefreshListener fragmentRefreshListenerMilestone;
|
private FragmentRefreshListener fragmentRefreshListenerMilestone;
|
||||||
private FragmentRefreshListener fragmentRefreshListenerFiles;
|
private FragmentRefreshListener fragmentRefreshListenerFiles;
|
||||||
private FragmentRefreshListener fragmentRefreshListenerFilterIssuesByMilestone;
|
private FragmentRefreshListener fragmentRefreshListenerFilterIssuesByMilestone;
|
||||||
|
private FragmentRefreshListener fragmentRefreshListenerReleases;
|
||||||
|
|
||||||
private String repositoryOwner;
|
private String repositoryOwner;
|
||||||
private String repositoryName;
|
private String repositoryName;
|
||||||
@ -388,6 +390,11 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
|||||||
ctx.startActivity(intent);
|
ctx.startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if(id == R.id.filterReleases && new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.15.0")) {
|
||||||
|
BottomSheetReleasesTagsFragment bottomSheetReleasesTagsFragment = new BottomSheetReleasesTagsFragment();
|
||||||
|
bottomSheetReleasesTagsFragment.show(getSupportFragmentManager(), "repoFilterReleasesMenuBottomSheet");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
|
||||||
@ -498,6 +505,16 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
|||||||
|
|
||||||
startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
|
startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
|
||||||
break;
|
break;
|
||||||
|
case "tags":
|
||||||
|
if(getFragmentRefreshListenerReleases() != null) {
|
||||||
|
getFragmentRefreshListenerReleases().onRefresh("tags");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "releases":
|
||||||
|
if(getFragmentRefreshListenerReleases() != null) {
|
||||||
|
getFragmentRefreshListenerReleases().onRefresh("releases");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,4 +836,9 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
|
|||||||
|
|
||||||
public void setFragmentRefreshListenerFiles(FragmentRefreshListener fragmentRefreshListenerFiles) { this.fragmentRefreshListenerFiles = fragmentRefreshListenerFiles; }
|
public void setFragmentRefreshListenerFiles(FragmentRefreshListener fragmentRefreshListenerFiles) { this.fragmentRefreshListenerFiles = fragmentRefreshListenerFiles; }
|
||||||
|
|
||||||
|
//Releases interface
|
||||||
|
public FragmentRefreshListener getFragmentRefreshListenerReleases() { return fragmentRefreshListenerReleases; }
|
||||||
|
|
||||||
|
public void setFragmentRefreshListenerReleases(FragmentRefreshListener fragmentRefreshListener) { this.fragmentRefreshListenerReleases = fragmentRefreshListener; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,12 @@ import java.util.Locale;
|
|||||||
|
|
||||||
public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.ReleasesViewHolder> {
|
public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.ReleasesViewHolder> {
|
||||||
|
|
||||||
private final List<Releases> releasesList;
|
private List<Releases> releasesList;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
private OnLoadMoreListener loadMoreListener;
|
||||||
|
private boolean isLoading = false, isMoreDataAvailable = true;
|
||||||
|
|
||||||
static class ReleasesViewHolder extends RecyclerView.ViewHolder {
|
static class ReleasesViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private Releases releases;
|
private Releases releases;
|
||||||
@ -172,6 +175,11 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
|
|||||||
|
|
||||||
ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets());
|
ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets());
|
||||||
holder.downloadList.setAdapter(adapter);
|
holder.downloadList.setAdapter(adapter);
|
||||||
|
|
||||||
|
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
|
||||||
|
isLoading = true;
|
||||||
|
loadMoreListener.onLoadMore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -179,4 +187,32 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
|
|||||||
return releasesList.size();
|
return releasesList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
||||||
|
isMoreDataAvailable = moreDataAvailable;
|
||||||
|
if(!isMoreDataAvailable) {
|
||||||
|
loadMoreListener.onLoadFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Releases> list) {
|
||||||
|
releasesList = list;
|
||||||
|
notifyDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
174
app/src/main/java/org/mian/gitnex/adapters/TagsAdapter.java
Normal file
174
app/src/main/java/org/mian/gitnex/adapters/TagsAdapter.java
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package org.mian.gitnex.adapters;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
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.core.text.HtmlCompat;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||||
|
import org.gitnex.tea4j.models.GitTag;
|
||||||
|
import org.mian.gitnex.R;
|
||||||
|
import org.mian.gitnex.helpers.AlertDialogs;
|
||||||
|
import org.mian.gitnex.helpers.Markdown;
|
||||||
|
import org.mian.gitnex.helpers.TinyDB;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author qwerty287
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TagsAdapter extends RecyclerView.Adapter<TagsAdapter.TagsViewHolder> {
|
||||||
|
|
||||||
|
private List<GitTag> tags;
|
||||||
|
private final Context context;
|
||||||
|
private final String repo;
|
||||||
|
private final String owner;
|
||||||
|
private Context ctx;
|
||||||
|
|
||||||
|
private OnLoadMoreListener loadMoreListener;
|
||||||
|
private boolean isLoading = false, isMoreDataAvailable = true;
|
||||||
|
|
||||||
|
static class TagsViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private final TextView tagName;
|
||||||
|
private final TextView tagBody;
|
||||||
|
private final LinearLayout downloadFrame;
|
||||||
|
private final LinearLayout downloads;
|
||||||
|
private final TextView releaseZipDownload;
|
||||||
|
private final TextView releaseTarDownload;
|
||||||
|
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);
|
||||||
|
downloadFrame = itemView.findViewById(R.id.downloadFrame);
|
||||||
|
downloads = itemView.findViewById(R.id.downloads);
|
||||||
|
releaseZipDownload = itemView.findViewById(R.id.releaseZipDownload);
|
||||||
|
releaseTarDownload = itemView.findViewById(R.id.releaseTarDownload);
|
||||||
|
downloadDropdownIcon = itemView.findViewById(R.id.downloadDropdownIcon);
|
||||||
|
options = itemView.findViewById(R.id.tagsOptionsMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TagsAdapter(Context ctx, List<GitTag> releasesMain, String repoOwner, String repoName) {
|
||||||
|
this.context = ctx;
|
||||||
|
this.tags = releasesMain;
|
||||||
|
owner = repoOwner;
|
||||||
|
repo = repoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
|
||||||
|
GitTag currentItem = tags.get(position);
|
||||||
|
|
||||||
|
holder.tagName.setText(currentItem.getName());
|
||||||
|
|
||||||
|
if(!currentItem.getMessage().equals("")) {
|
||||||
|
Markdown.render(context, currentItem.getMessage(), holder.tagBody);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
holder.tagBody.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.downloadFrame.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(!TinyDB.getInstance(ctx).getBoolean("isRepoAdmin")) {
|
||||||
|
holder.options.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.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 -> {
|
||||||
|
AlertDialogs.tagDeleteDialog(context, currentItem.getName(), owner, repo);
|
||||||
|
dialog.dismiss();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.releaseZipDownload.setText(
|
||||||
|
HtmlCompat.fromHtml("<a href='" + currentItem.getZipballUrl() + "'>" + context.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> ", HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||||
|
holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
|
holder.releaseTarDownload.setText(
|
||||||
|
HtmlCompat.fromHtml("<a href='" + currentItem.getTarballUrl() + "'>" + context.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> ", HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||||
|
holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GitTag> list) {
|
||||||
|
tags = list;
|
||||||
|
notifyDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package org.mian.gitnex.fragments;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
|
import org.mian.gitnex.databinding.BottomSheetReleasesTagsBinding;
|
||||||
|
import org.mian.gitnex.structs.BottomSheetListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author opyale
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BottomSheetReleasesTagsFragment extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
|
private BottomSheetListener bmListener;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
|
||||||
|
super.onAttach(context);
|
||||||
|
|
||||||
|
try {
|
||||||
|
bmListener = (BottomSheetListener) context;
|
||||||
|
}
|
||||||
|
catch(ClassCastException e) {
|
||||||
|
throw new ClassCastException(context.toString() + " must implement BottomSheetListener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
BottomSheetReleasesTagsBinding binding = BottomSheetReleasesTagsBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
binding.tags.setOnClickListener(v1 -> {
|
||||||
|
|
||||||
|
bmListener.onButtonClicked("tags");
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.releases.setOnClickListener(v12 -> {
|
||||||
|
|
||||||
|
bmListener.onButtonClicked("releases");
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ import android.os.Bundle;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
@ -19,10 +21,14 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import org.gitnex.tea4j.models.Releases;
|
import org.gitnex.tea4j.models.Releases;
|
||||||
|
import org.mian.gitnex.R;
|
||||||
|
import org.mian.gitnex.activities.RepoDetailActivity;
|
||||||
import org.mian.gitnex.adapters.ReleasesAdapter;
|
import org.mian.gitnex.adapters.ReleasesAdapter;
|
||||||
|
import org.mian.gitnex.adapters.TagsAdapter;
|
||||||
import org.mian.gitnex.databinding.FragmentReleasesBinding;
|
import org.mian.gitnex.databinding.FragmentReleasesBinding;
|
||||||
import org.mian.gitnex.helpers.Authorization;
|
import org.mian.gitnex.helpers.Authorization;
|
||||||
import org.mian.gitnex.helpers.TinyDB;
|
import org.mian.gitnex.helpers.TinyDB;
|
||||||
|
import org.mian.gitnex.helpers.Version;
|
||||||
import org.mian.gitnex.viewmodels.ReleasesViewModel;
|
import org.mian.gitnex.viewmodels.ReleasesViewModel;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -34,6 +40,7 @@ public class ReleasesFragment extends Fragment {
|
|||||||
|
|
||||||
private ProgressBar mProgressBar;
|
private ProgressBar mProgressBar;
|
||||||
private ReleasesAdapter adapter;
|
private ReleasesAdapter adapter;
|
||||||
|
private TagsAdapter tagsAdapter;
|
||||||
private RecyclerView mRecyclerView;
|
private RecyclerView mRecyclerView;
|
||||||
private TextView noDataReleases;
|
private TextView noDataReleases;
|
||||||
private static String repoNameF = "param2";
|
private static String repoNameF = "param2";
|
||||||
@ -42,6 +49,9 @@ public class ReleasesFragment extends Fragment {
|
|||||||
private String repoName;
|
private String repoName;
|
||||||
private String repoOwner;
|
private String repoOwner;
|
||||||
private String releaseTag;
|
private String releaseTag;
|
||||||
|
private boolean viewTypeIsTags = false;
|
||||||
|
private int page = 1;
|
||||||
|
private int pageReleases = 1;
|
||||||
|
|
||||||
private OnFragmentInteractionListener mListener;
|
private OnFragmentInteractionListener mListener;
|
||||||
|
|
||||||
@ -90,12 +100,30 @@ public class ReleasesFragment extends Fragment {
|
|||||||
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
|
|
||||||
swipeRefresh.setRefreshing(false);
|
swipeRefresh.setRefreshing(false);
|
||||||
|
if(viewTypeIsTags) {
|
||||||
|
ReleasesViewModel.loadTagsList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
} else {
|
||||||
ReleasesViewModel.loadReleasesList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
ReleasesViewModel.loadReleasesList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
}
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
}, 50));
|
}, 50));
|
||||||
|
|
||||||
fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName);
|
fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName);
|
||||||
|
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
((RepoDetailActivity) requireActivity()).setFragmentRefreshListenerReleases(type -> {
|
||||||
|
viewTypeIsTags = type.equals("tags");
|
||||||
|
page = 1;
|
||||||
|
pageReleases = 1;
|
||||||
|
if(viewTypeIsTags) {
|
||||||
|
ReleasesViewModel.loadTagsList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
} else {
|
||||||
|
ReleasesViewModel.loadReleasesList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
}
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
});
|
||||||
|
|
||||||
return fragmentReleasesBinding.getRoot();
|
return fragmentReleasesBinding.getRoot();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -107,10 +135,14 @@ public class ReleasesFragment extends Fragment {
|
|||||||
TinyDB tinyDb = TinyDB.getInstance(getContext());
|
TinyDB tinyDb = TinyDB.getInstance(getContext());
|
||||||
|
|
||||||
if(tinyDb.getBoolean("updateReleases")) {
|
if(tinyDb.getBoolean("updateReleases")) {
|
||||||
|
if(viewTypeIsTags) {
|
||||||
|
ReleasesViewModel.loadTagsList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
} else {
|
||||||
ReleasesViewModel.loadReleasesList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
ReleasesViewModel.loadReleasesList(Authorization.get(getContext()), repoOwner, repoName, getContext());
|
||||||
|
}
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
tinyDb.putBoolean("updateReleases", false);
|
tinyDb.putBoolean("updateReleases", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onButtonPressed(Uri uri) {
|
public void onButtonPressed(Uri uri) {
|
||||||
@ -136,7 +168,22 @@ public class ReleasesFragment extends Fragment {
|
|||||||
releasesModel.getReleasesList(instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Releases>>() {
|
releasesModel.getReleasesList(instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Releases>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(@Nullable List<Releases> releasesListMain) {
|
public void onChanged(@Nullable List<Releases> releasesListMain) {
|
||||||
|
if(!viewTypeIsTags) {
|
||||||
adapter = new ReleasesAdapter(getContext(), releasesListMain);
|
adapter = new ReleasesAdapter(getContext(), releasesListMain);
|
||||||
|
adapter.setLoadMoreListener(new ReleasesAdapter.OnLoadMoreListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMore() {
|
||||||
|
pageReleases += 1;
|
||||||
|
ReleasesViewModel.loadMoreReleases(instanceToken, owner, repo , pageReleases, getContext(), adapter);
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished() {
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
if(adapter.getItemCount() > 0) {
|
if(adapter.getItemCount() > 0) {
|
||||||
mRecyclerView.setAdapter(adapter);
|
mRecyclerView.setAdapter(adapter);
|
||||||
if(releasesListMain != null && releaseTag != null) {
|
if(releasesListMain != null && releaseTag != null) {
|
||||||
@ -155,6 +202,37 @@ public class ReleasesFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
mProgressBar.setVisibility(View.GONE);
|
mProgressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
releasesModel.getTagsList(instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), tagList -> {
|
||||||
|
if(viewTypeIsTags) {
|
||||||
|
tagsAdapter = new TagsAdapter(getContext(), tagList, owner, repo);
|
||||||
|
tagsAdapter.setLoadMoreListener(new TagsAdapter.OnLoadMoreListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMore() {
|
||||||
|
page += 1;
|
||||||
|
ReleasesViewModel.loadMoreTags(instanceToken, owner, repo , page, getContext(), tagsAdapter);
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished() {
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(tagsAdapter.getItemCount() > 0) {
|
||||||
|
mRecyclerView.setAdapter(tagsAdapter);
|
||||||
|
noDataReleases.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tagsAdapter.notifyDataSetChanged();
|
||||||
|
mRecyclerView.setAdapter(tagsAdapter);
|
||||||
|
noDataReleases.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -168,4 +246,11 @@ public class ReleasesFragment extends Fragment {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||||
|
if(new Version(TinyDB.getInstance(requireContext()).getString("giteaVersion")).less("1.15.0"))
|
||||||
|
return;
|
||||||
|
inflater.inflate(R.menu.filter_menu_releases, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import android.content.Intent;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import org.mian.gitnex.R;
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.actions.CollaboratorActions;
|
import org.mian.gitnex.actions.CollaboratorActions;
|
||||||
@ -13,6 +14,10 @@ import org.mian.gitnex.actions.PullRequestActions;
|
|||||||
import org.mian.gitnex.actions.TeamActions;
|
import org.mian.gitnex.actions.TeamActions;
|
||||||
import org.mian.gitnex.activities.CreateLabelActivity;
|
import org.mian.gitnex.activities.CreateLabelActivity;
|
||||||
import org.mian.gitnex.activities.LoginActivity;
|
import org.mian.gitnex.activities.LoginActivity;
|
||||||
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Author M M Arif
|
* Author M M Arif
|
||||||
@ -87,6 +92,34 @@ public class AlertDialogs {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void tagDeleteDialog(final Context context, final String tagName, final String owner, final String repo) {
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setTitle(String.format(context.getString(R.string.deleteTagTitle), tagName))
|
||||||
|
.setMessage(R.string.deleteTagConfirmation)
|
||||||
|
.setIcon(R.drawable.ic_delete)
|
||||||
|
.setPositiveButton(R.string.menuDeleteText, (dialog, whichButton) -> RetrofitClient.getApiInterface(context).deleteTag(Authorization.get(context), owner, repo, tagName).enqueue(new Callback<Void>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
|
||||||
|
if(response.isSuccessful()) {
|
||||||
|
Toasty.success(context, context.getString(R.string.tagDeleted));
|
||||||
|
}
|
||||||
|
else if(response.code() == 403) {
|
||||||
|
Toasty.error(context, context.getString(R.string.authorizeError));
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
public static void collaboratorRemoveDialog(final Context context, final String userNameMain, String title, String message, String positiveButton, String negativeButton, final String searchKeyword) {
|
public static void collaboratorRemoveDialog(final Context context, final String userNameMain, String title, String message, String positiveButton, String negativeButton, final String searchKeyword) {
|
||||||
|
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
|
@ -6,8 +6,14 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
import org.gitnex.tea4j.models.GitTag;
|
||||||
import org.gitnex.tea4j.models.Releases;
|
import org.gitnex.tea4j.models.Releases;
|
||||||
|
import org.mian.gitnex.adapters.ReleasesAdapter;
|
||||||
|
import org.mian.gitnex.adapters.TagsAdapter;
|
||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
|
import org.mian.gitnex.helpers.Constants;
|
||||||
|
import org.mian.gitnex.helpers.TinyDB;
|
||||||
|
import org.mian.gitnex.helpers.Version;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
@ -20,10 +26,17 @@ import retrofit2.Response;
|
|||||||
public class ReleasesViewModel extends ViewModel {
|
public class ReleasesViewModel extends ViewModel {
|
||||||
|
|
||||||
private static MutableLiveData<List<Releases>> releasesList;
|
private static MutableLiveData<List<Releases>> releasesList;
|
||||||
|
private static int resultLimit = Constants.resultLimitOldGiteaInstances;
|
||||||
|
|
||||||
public LiveData<List<Releases>> getReleasesList(String token, String owner, String repo, Context ctx) {
|
public LiveData<List<Releases>> getReleasesList(String token, String owner, String repo, Context ctx) {
|
||||||
|
|
||||||
releasesList = new MutableLiveData<>();
|
releasesList = new MutableLiveData<>();
|
||||||
|
|
||||||
|
// if gitea is 1.12 or higher use the new limit
|
||||||
|
if(new Version(TinyDB.getInstance(ctx).getString("giteaVersion")).higherOrEqual("1.12.0")) {
|
||||||
|
resultLimit = Constants.resultLimitNewGiteaInstances;
|
||||||
|
}
|
||||||
|
|
||||||
loadReleasesList(token, owner, repo, ctx);
|
loadReleasesList(token, owner, repo, ctx);
|
||||||
|
|
||||||
return releasesList;
|
return releasesList;
|
||||||
@ -33,7 +46,7 @@ public class ReleasesViewModel extends ViewModel {
|
|||||||
|
|
||||||
Call<List<Releases>> call = RetrofitClient
|
Call<List<Releases>> call = RetrofitClient
|
||||||
.getApiInterface(ctx)
|
.getApiInterface(ctx)
|
||||||
.getReleases(token, owner, repo);
|
.getReleases(token, owner, repo, 1, resultLimit);
|
||||||
|
|
||||||
call.enqueue(new Callback<List<Releases>>() {
|
call.enqueue(new Callback<List<Releases>>() {
|
||||||
|
|
||||||
@ -42,18 +55,130 @@ public class ReleasesViewModel extends ViewModel {
|
|||||||
|
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
releasesList.postValue(response.body());
|
releasesList.postValue(response.body());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Log.i("onResponse", String.valueOf(response.code()));
|
Log.i("onResponse", String.valueOf(response.code()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NonNull Call<List<Releases>> call, Throwable t) {
|
public void onFailure(@NonNull Call<List<Releases>> call, Throwable t) {
|
||||||
Log.i("onFailure", t.toString());
|
Log.i("onFailure", t.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadMoreReleases(String token, String owner, String repo, int page, Context ctx, ReleasesAdapter adapter) {
|
||||||
|
|
||||||
|
Call<List<Releases>> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.getReleases(token, owner, repo, page, resultLimit);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<List<Releases>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<Releases>> call, @NonNull Response<List<Releases>> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
List<Releases> list = releasesList.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 {
|
||||||
|
Log.i("onResponse", String.valueOf(response.code()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<List<Releases>> call, @NonNull Throwable t) {
|
||||||
|
Log.i("onFailure", t.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MutableLiveData<List<GitTag>> tagsList;
|
||||||
|
|
||||||
|
public LiveData<List<GitTag>> getTagsList(String token, String owner, String repo, Context ctx) {
|
||||||
|
|
||||||
|
tagsList = new MutableLiveData<>();
|
||||||
|
|
||||||
|
// if gitea is 1.12 or higher use the new limit
|
||||||
|
if(new Version(TinyDB.getInstance(ctx).getString("giteaVersion")).higherOrEqual("1.12.0")) {
|
||||||
|
resultLimit = Constants.resultLimitNewGiteaInstances;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTagsList(token, owner, repo, ctx);
|
||||||
|
|
||||||
|
return tagsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadTagsList(String token, String owner, String repo, Context ctx) {
|
||||||
|
|
||||||
|
Call<List<GitTag>> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.getTags(token, owner, repo, 1, resultLimit);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<List<GitTag>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<GitTag>> call, @NonNull Response<List<GitTag>> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
tagsList.postValue(response.body());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.i("onResponse", String.valueOf(response.code()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<List<GitTag>> call, @NonNull Throwable t) {
|
||||||
|
Log.i("onFailure", t.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public static void loadMoreTags(String token, String owner, String repo, int page, Context ctx, TagsAdapter adapter) {
|
||||||
|
|
||||||
|
Call<List<GitTag>> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.getTags(token, owner, repo, page, resultLimit);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<List<GitTag>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<GitTag>> call, @NonNull Response<List<GitTag>> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
|
||||||
|
List<GitTag> list = tagsList.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 {
|
||||||
|
Log.i("onResponse", String.valueOf(response.code()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<List<GitTag>> call, @NonNull Throwable t) {
|
||||||
|
Log.i("onFailure", t.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,14 @@
|
|||||||
android:text="@string/newCreateButtonCopy"
|
android:text="@string/newCreateButtonCopy"
|
||||||
android:textColor="@color/btnTextColor" />
|
android:textColor="@color/btnTextColor" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/createNewTag"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/create_tag"
|
||||||
|
android:textColor="@color/btnTextColor" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
53
app/src/main/res/layout/bottom_sheet_releases_tags.xml
Normal file
53
app/src/main/res/layout/bottom_sheet_releases_tags.xml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:background="?attr/primaryBackgroundColor">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/releases"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:focusable="true"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="24dp"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/tabTextReleases"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_release" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tags"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:focusable="true"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="24dp"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/tags"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_label" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
40
app/src/main/res/layout/bottom_sheet_tag_in_list.xml
Normal file
40
app/src/main/res/layout/bottom_sheet_tag_in_list.xml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:background="?attr/primaryBackgroundColor">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tagMenuDelete"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:focusable="true"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="24dp"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/menuDeleteText"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_delete" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
150
app/src/main/res/layout/list_tags.xml
Normal file
150
app/src/main/res/layout/list_tags.xml
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/headerFrame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tagName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.9"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/tagsOptionsMenu"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:contentDescription="@string/labelMenuContentDesc"
|
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/ic_dotted_menu_horizontal" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bodyFrame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tagBodyContent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="web|email"
|
||||||
|
android:textColorLink="@color/lightBlue"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/downloadFrame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/downloadDropdownIcon"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/generalImgContentText"
|
||||||
|
app:tint="?attr/primaryTextColor"
|
||||||
|
android:src="@drawable/ic_chevron_right"
|
||||||
|
app:srcCompat="@drawable/ic_chevron_right" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="3dp"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="@string/releaseDownloadText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/downloads"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:paddingTop="8dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
app:srcCompat="@drawable/ic_download"
|
||||||
|
android:contentDescription="@string/generalImgContentText" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/releaseZipDownload"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
app:srcCompat="@drawable/ic_download"
|
||||||
|
android:contentDescription="@string/generalImgContentText" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/releaseTarDownload"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
12
app/src/main/res/menu/filter_menu_releases.xml
Normal file
12
app/src/main/res/menu/filter_menu_releases.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/filterReleases"
|
||||||
|
android:icon="@drawable/ic_filter"
|
||||||
|
android:title="@string/releasesTags"
|
||||||
|
android:orderInCategory="0"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
</menu>
|
@ -753,6 +753,14 @@
|
|||||||
<string name="closePr">Close Pull Request</string>
|
<string name="closePr">Close Pull Request</string>
|
||||||
<string name="reopenPr">Reopen Pull Request</string>
|
<string name="reopenPr">Reopen Pull Request</string>
|
||||||
<string name="userAvatar">Avatar</string>
|
<string name="userAvatar">Avatar</string>
|
||||||
|
<string name="tags">Tags</string>
|
||||||
|
<string name="releasesTags">Releases/Tags</string>
|
||||||
|
<string name="create_tag">Create Tag Only</string>
|
||||||
|
<string name="tagCreated">Tag created</string>
|
||||||
|
<string name="asRef">Use as reference</string>
|
||||||
|
<string name="deleteTagConfirmation">Do you really want to delete this tag?</string>
|
||||||
|
<string name="deleteTagTitle">Delete tag %s</string>
|
||||||
|
<string name="tagDeleted">Tag deleted</string>
|
||||||
<string name="useCustomTabs">Use Custom Tabs</string>
|
<string name="useCustomTabs">Use Custom Tabs</string>
|
||||||
<string name="browserOpenFailed">No application found to open this link. SSH URLs and URLs with another prefix the http:// or https:// are not supported by most browser</string>
|
<string name="browserOpenFailed">No application found to open this link. SSH URLs and URLs with another prefix the http:// or https:// are not supported by most browser</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user