diff --git a/app/build.gradle b/app/build.gradle
index bcd7572a..118beb5a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -23,7 +23,7 @@ android {
}
dependencies {
- def lifecycle_version = "2.2.0-rc01"
+ def lifecycle_version = "2.2.0-rc02"
final def markwon_version = "4.1.1"
implementation fileTree(include: ['*.jar'], dir: 'libs')
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b2bef5fa..3d0157b8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -66,6 +66,7 @@
+
diff --git a/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java b/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java
index d98fd0ad..7b7887be 100644
--- a/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java
@@ -100,7 +100,13 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
editIssueButton.setOnClickListener(this);
if(!tinyDb.getString("issueNumber").isEmpty()) {
- toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
+
+ if(tinyDb.getString("issueType").equals("pr")) {
+ toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex)));
+ }
+ else {
+ toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
+ }
}
disableProcessButton();
@@ -240,7 +246,13 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
if(response.code() == 201) {
- Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
+ if(tinyDb.getString("issueType").equals("pr")) {
+ Toasty.info(getApplicationContext(), getString(R.string.editPrSuccessMessage));
+ }
+ else {
+ Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
+ }
+
tinyDb.putBoolean("issueEdited", true);
tinyDb.putBoolean("resumeIssues", true);
finish();
diff --git a/app/src/main/java/org/mian/gitnex/activities/FileDiffActivity.java b/app/src/main/java/org/mian/gitnex/activities/FileDiffActivity.java
new file mode 100644
index 00000000..660656fe
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/activities/FileDiffActivity.java
@@ -0,0 +1,212 @@
+package org.mian.gitnex.activities;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import org.apache.commons.io.FilenameUtils;
+import org.mian.gitnex.R;
+import org.mian.gitnex.adapters.FilesDiffAdapter;
+import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.helpers.AlertDialogs;
+import org.mian.gitnex.helpers.Toasty;
+import org.mian.gitnex.models.FileDiffView;
+import org.mian.gitnex.util.AppUtil;
+import org.mian.gitnex.util.TinyDB;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+
+/**
+ * Author M M Arif
+ */
+
+public class FileDiffActivity extends AppCompatActivity {
+
+ private View.OnClickListener onClickListener;
+ private TextView toolbar_title;
+ private RecyclerView mRecyclerView;
+ private ProgressBar mProgressBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_file_diff);
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final TinyDB tinyDb = new TinyDB(getApplicationContext());
+ String repoFullName = tinyDb.getString("repoFullName");
+ String[] parts = repoFullName.split("/");
+ final String repoOwner = parts[0];
+ final String repoName = parts[1];
+ final String instanceUrl = tinyDb.getString("instanceUrl");
+ final String loginUid = tinyDb.getString("loginUid");
+ final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+
+ ImageView closeActivity = findViewById(R.id.close);
+ toolbar_title = findViewById(R.id.toolbar_title);
+ mRecyclerView = findViewById(R.id.recyclerView);
+ mProgressBar = findViewById(R.id.progress_bar);
+
+ mRecyclerView.setHasFixedSize(true);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
+
+ toolbar_title.setText(R.string.processingText);
+ initCloseListener();
+ closeActivity.setOnClickListener(onClickListener);
+
+ mProgressBar.setVisibility(View.VISIBLE);
+
+ String fileDiffName = tinyDb.getString("issueNumber")+".diff";
+
+ getFileContents(tinyDb.getString("instanceUrlWithProtocol"), repoOwner, repoName, fileDiffName);
+
+ }
+
+ private void getFileContents(String instanceUrl, String owner, String repo, String filename) {
+
+ Call call = RetrofitClient
+ .getInstance(instanceUrl, getApplicationContext())
+ .getApiInterface()
+ .getFileDiffContents(owner, repo, filename);
+
+ call.enqueue(new Callback() {
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {
+
+ if (response.code() == 200) {
+
+ try {
+ assert response.body() != null;
+
+ AppUtil appUtil = new AppUtil();
+ List fileContentsArray = new ArrayList<>();
+
+ String[] lines = response.body().string().split("diff");
+
+ if(lines.length > 0) {
+
+ for (int i = 1; i < lines.length; i++) {
+
+ if(lines[i].contains("@@ -")) {
+
+ String[] level2nd = lines[i].split("@@ -"); // main content part of single diff view
+
+ String[] fileName_ = level2nd[0].split("\\+\\+\\+ b/"); // filename part
+ String fileNameFinal = fileName_[1];
+
+ String[] fileContents_ = level2nd[1].split("@@"); // file info / content part
+ String fileInfoFinal = fileContents_[0];
+ String fileContentsFinal = (fileContents_[1]);
+
+ if(level2nd.length > 2) {
+ for (int j = 2; j < level2nd.length; j++) {
+ fileContentsFinal += (level2nd[j]);
+ }
+ }
+
+ String fileExtension = FilenameUtils.getExtension(fileNameFinal);
+
+ String fileContentsFinalWithBlankLines = fileContentsFinal.replaceAll( ".*@@.*", "" );
+ String fileContentsFinalWithoutBlankLines = fileContentsFinal.replaceAll( ".*@@.*(\r?\n|\r)?", "" );
+ fileContentsFinalWithoutBlankLines = fileContentsFinalWithoutBlankLines.replaceAll( ".*\\ No newline at end of file.*(\r?\n|\r)?", "" );
+
+ fileContentsArray.add(new FileDiffView(fileNameFinal, appUtil.imageExtension(fileExtension), fileInfoFinal, fileContentsFinalWithoutBlankLines));
+ }
+ else {
+
+ String[] getFileName = lines[i].split("--git a/");
+
+ String[] getFileName_ = getFileName[1].split("b/");
+ String getFileNameFinal = getFileName_[0].trim();
+
+ String[] binaryFile = getFileName_[1].split("GIT binary patch");
+ String binaryFileRaw = binaryFile[1].substring(binaryFile[1].indexOf('\n')+1);
+ String binaryFileFinal = binaryFile[1].substring(binaryFileRaw.indexOf('\n')+1);
+
+ String fileExtension = FilenameUtils.getExtension(getFileNameFinal);
+
+ fileContentsArray.add(new FileDiffView(getFileNameFinal, appUtil.imageExtension(fileExtension),"", binaryFileFinal));
+ }
+
+ }
+
+ }
+
+ int filesCount = fileContentsArray.size();
+ if(filesCount > 1) {
+ toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
+ }
+ else {
+ toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
+ }
+
+ FilesDiffAdapter adapter = new FilesDiffAdapter(fileContentsArray, getApplicationContext());
+ mRecyclerView.setAdapter(adapter);
+
+ mProgressBar.setVisibility(View.GONE);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ else if(response.code() == 401) {
+
+ AlertDialogs.authorizationTokenRevokedDialog(getApplicationContext(), getResources().getString(R.string.alertDialogTokenRevokedTitle),
+ getResources().getString(R.string.alertDialogTokenRevokedMessage),
+ getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
+ getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
+
+ }
+ else if(response.code() == 403) {
+
+ Toasty.info(getApplicationContext(), getApplicationContext().getString(R.string.authorizeError));
+
+ }
+ else if(response.code() == 404) {
+
+ Toasty.info(getApplicationContext(), getApplicationContext().getString(R.string.apiNotFound));
+
+ }
+ else {
+
+ Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
+
+ }
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+ Log.e("onFailure", t.toString());
+ }
+ });
+
+ }
+
+ private void initCloseListener() {
+ onClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ getIntent().removeExtra("singleFileName");
+ finish();
+ }
+ };
+ }
+
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java b/app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java
index fb36b4f9..f5ac58e9 100644
--- a/app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java
@@ -226,6 +226,7 @@ public class ReplyToIssueActivity extends AppCompatActivity {
Toasty.info(getApplicationContext(), getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
+ tinyDb.putBoolean("resumePullRequests", true);
finish();
}
diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
index 7959080a..1bc60fd9 100644
--- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
@@ -31,6 +31,7 @@ import org.mian.gitnex.fragments.FilesFragment;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.fragments.LabelsFragment;
import org.mian.gitnex.fragments.MilestonesFragment;
+import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoBottomSheetFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
@@ -213,15 +214,18 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
case 3: // closed issues
fragment = new ClosedIssuesFragment();
break;
- case 4: // milestones
+ case 4: // pull requests
+ fragment = new PullRequestsFragment();
+ break;
+ case 5: // milestones
return MilestonesFragment.newInstance(repoOwner, repoName);
- case 5: // labels
+ case 6: // labels
return LabelsFragment.newInstance(repoOwner, repoName);
- case 6: // branches
+ case 7: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
- case 7: // releases
+ case 8: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
- case 8: // collaborators
+ case 9: // collaborators
return CollaboratorsFragment.newInstance(repoOwner, repoName);
}
return fragment;
@@ -229,7 +233,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
@Override
public int getCount() {
- return 9;
+ return 10;
}
}
diff --git a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
index 19d7a05a..d8859ff8 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/ClosedIssuesAdapter.java
@@ -11,6 +11,7 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
@@ -109,7 +110,7 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));
diff --git a/app/src/main/java/org/mian/gitnex/adapters/FilesDiffAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/FilesDiffAdapter.java
new file mode 100644
index 00000000..5cd20c7a
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/adapters/FilesDiffAdapter.java
@@ -0,0 +1,138 @@
+package org.mian.gitnex.adapters;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.HorizontalScrollView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import org.mian.gitnex.R;
+import org.mian.gitnex.models.FileDiffView;
+import java.util.List;
+
+/**
+ * Author M M Arif
+ */
+
+public class FilesDiffAdapter extends RecyclerView.Adapter {
+
+ private List dataList;
+ private Context ctx;
+
+ static class FilesDiffViewHolder extends RecyclerView.ViewHolder {
+
+ private TextView fileContents;
+ private TextView fileName;
+ private TextView fileInfo;
+ private ImageView fileImage;
+ private HorizontalScrollView fileContentsView;
+ private LinearLayout allLines;
+
+ private FilesDiffViewHolder(View itemView) {
+ super(itemView);
+
+ fileContents = itemView.findViewById(R.id.fileContents);
+ fileName = itemView.findViewById(R.id.fileName);
+ fileInfo = itemView.findViewById(R.id.fileInfo);
+ fileImage = itemView.findViewById(R.id.fileImage);
+ fileContentsView = itemView.findViewById(R.id.fileContentsView);
+ allLines = itemView.findViewById(R.id.allLinesLayout);
+
+ }
+ }
+
+ public FilesDiffAdapter(List dataListMain, Context ctx) {
+ this.dataList = dataListMain;
+ this.ctx = ctx;
+ }
+
+ @NonNull
+ @Override
+ public FilesDiffAdapter.FilesDiffViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_diffs_list, parent, false);
+ return new FilesDiffAdapter.FilesDiffViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull FilesDiffViewHolder holder, int position) {
+
+ FileDiffView data = dataList.get(position);
+
+ if(data.isFileType()) {
+
+ holder.fileName.setText(data.getFileName());
+
+ holder.fileInfo.setVisibility(View.GONE);
+
+ //byte[] imageData = Base64.decode(data.getFileContents(), Base64.DEFAULT);
+ //Drawable imageDrawable = new BitmapDrawable(ctx.getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
+ //holder.fileImage.setImageDrawable(imageDrawable);
+ holder.fileContentsView.setVisibility(View.GONE);
+
+ }
+ else {
+
+ String[] splitData = data.getFileContents().split("\\R");
+
+ for (String eachSplit : splitData) {
+
+ TextView textLine = new TextView(ctx);
+ textLine.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+
+ if (eachSplit.startsWith("+")) {
+
+ textLine.setText(eachSplit);
+ holder.allLines.addView(textLine);
+
+ textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
+ textLine.setPadding(5, 5, 5, 5);
+ textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffAddedColor));
+
+ }
+ else if (eachSplit.startsWith("-")) {
+
+ textLine.setText(eachSplit);
+ holder.allLines.addView(textLine);
+
+ textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
+ textLine.setPadding(5, 5, 5, 5);
+ textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffRemovedColor));
+
+ }
+ else {
+
+ if(eachSplit.length() > 0) {
+ textLine.setText(eachSplit);
+ holder.allLines.addView(textLine);
+
+ textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
+ textLine.setPadding(5, 5, 5, 5);
+ textLine.setBackgroundColor(ctx.getResources().getColor(R.color.white));
+ }
+
+ }
+
+ }
+
+ holder.fileName.setText(data.getFileName());
+ if(!data.getFileInfo().equals("")) {
+ holder.fileInfo.setText(ctx.getResources().getString(R.string.fileDiffInfoChanges, data.getFileInfo()));
+ }
+ else {
+ holder.fileInfo.setVisibility(View.GONE);
+ }
+
+ }
+
+ }
+
+ @Override
+ public int getItemCount() {
+ return dataList.size();
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java
index 5e6a8960..c91b5e51 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java
@@ -11,6 +11,7 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
@@ -109,7 +110,7 @@ public class IssuesAdapter extends RecyclerView.Adapter
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
- private ImageView issueType;
+ private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
@@ -121,7 +122,7 @@ public class IssuesAdapter extends RecyclerView.Adapter
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
- issueType = itemView.findViewById(R.id.issueType);
+ relativeLayoutFrame = itemView.findViewById(R.id.relativeLayoutFrame);
issueTitle.setOnClickListener(new View.OnClickListener() {
@Override
@@ -135,6 +136,7 @@ public class IssuesAdapter extends RecyclerView.Adapter
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
+ tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@@ -151,6 +153,7 @@ public class IssuesAdapter extends RecyclerView.Adapter
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
+ tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@@ -165,6 +168,13 @@ public class IssuesAdapter extends RecyclerView.Adapter
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
+ if(issuesModel.getPull_request() != null) {
+ if (!issuesModel.getPull_request().isMerged()) {
+ relativeLayoutFrame.setVisibility(View.GONE);
+ relativeLayoutFrame.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
+ }
+ }
+
if (!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
} else {
@@ -177,14 +187,6 @@ public class IssuesAdapter extends RecyclerView.Adapter
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
}
- if (issuesModel.getPull_request() == null) {
- issueType.setImageResource(R.drawable.ic_issues);
- issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypeIssue), context));
- } else {
- issueType.setImageResource(R.drawable.ic_merge);
- issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypePullRequest), context));
- }
-
String issueNumber_ = "" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));
diff --git a/app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java
index 35ac7f09..2304d6cb 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java
@@ -50,6 +50,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter implements Filterable {
+
+ private Context context;
+ private final int TYPE_LOAD = 0;
+ private List prList;
+ private List prListFull;
+ private PullRequestsAdapter.OnLoadMoreListener loadMoreListener;
+ private boolean isLoading = false, isMoreDataAvailable = true;
+
+ public PullRequestsAdapter(Context context, List prListMain) {
+
+ this.context = context;
+ this.prList = prListMain;
+ prListFull = new ArrayList<>(prList);
+
+ }
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+
+ LayoutInflater inflater = LayoutInflater.from(context);
+
+ if(viewType == TYPE_LOAD){
+ return new PullRequestsAdapter.PullRequestsHolder(inflater.inflate(R.layout.repo_pr_list, parent,false));
+ }
+ else {
+ return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
+ }
+
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+
+ if(position >= getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null) {
+
+ isLoading = true;
+ loadMoreListener.onLoadMore();
+
+ }
+
+ if(getItemViewType(position) == TYPE_LOAD) {
+
+ ((PullRequestsAdapter.PullRequestsHolder)holder).bindData(prList.get(position));
+
+ }
+
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+
+ if(prList.get(position).getTitle() != null) {
+ return TYPE_LOAD;
+ }
+ else {
+ return 1;
+ }
+
+ }
+
+ @Override
+ public int getItemCount() {
+
+ return prList.size();
+
+ }
+
+ class PullRequestsHolder extends RecyclerView.ViewHolder {
+
+ private TextView prNumber;
+ private ImageView assigneeAvatar;
+ private TextView prTitle;
+ private TextView prCreatedTime;
+ private TextView prCommentsCount;
+
+ PullRequestsHolder(View itemView) {
+
+ super(itemView);
+
+ prNumber = itemView.findViewById(R.id.prNumber);
+ assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
+ prTitle = itemView.findViewById(R.id.prTitle);
+ prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
+ LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
+ prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
+
+ prTitle.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ Context context = v.getContext();
+
+ Intent intent = new Intent(context, IssueDetailActivity.class);
+ intent.putExtra("issueNumber", prNumber.getText());
+
+ TinyDB tinyDb = new TinyDB(context);
+ tinyDb.putString("issueNumber", prNumber.getText().toString());
+ tinyDb.putString("issueType", "pr");
+ context.startActivity(intent);
+
+ }
+ });
+ frameCommentsCount.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ Context context = v.getContext();
+
+ Intent intent = new Intent(context, IssueDetailActivity.class);
+ intent.putExtra("issueNumber", prNumber.getText());
+
+ TinyDB tinyDb = new TinyDB(context);
+ tinyDb.putString("issueNumber", prNumber.getText().toString());
+ tinyDb.putString("issueType", "pr");
+ context.startActivity(intent);
+
+ }
+ });
+
+ }
+
+ @SuppressLint("SetTextI18n")
+ void bindData(PullRequests prModel){
+
+ final TinyDB tinyDb = new TinyDB(context);
+ final String locale = tinyDb.getString("locale");
+ final String timeFormat = tinyDb.getString("dateFormat");
+
+ if (!prModel.getUser().getFull_name().equals("")) {
+ assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getFull_name(), context));
+ } else {
+ assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getLogin(), context));
+ }
+
+ if (prModel.getUser().getAvatar_url() != null) {
+ Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
+ } else {
+ Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
+ }
+
+ String prNumber_ = "" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "";
+ prTitle.setText(Html.fromHtml(prNumber_ + " " + prModel.getTitle()));
+
+ prNumber.setText(String.valueOf(prModel.getNumber()));
+ prCommentsCount.setText(String.valueOf(prModel.getComments()));
+
+ switch (timeFormat) {
+ case "pretty": {
+ PrettyTime prettyTime = new PrettyTime(new Locale(locale));
+ String createdTime = prettyTime.format(prModel.getCreated_at());
+ prCreatedTime.setText(createdTime);
+ prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context));
+ break;
+ }
+ case "normal": {
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
+ String createdTime = formatter.format(prModel.getCreated_at());
+ prCreatedTime.setText(createdTime);
+ break;
+ }
+ case "normal1": {
+ DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
+ String createdTime = formatter.format(prModel.getCreated_at());
+ prCreatedTime.setText(createdTime);
+ break;
+ }
+ }
+
+ }
+
+ }
+
+ static class LoadHolder extends RecyclerView.ViewHolder {
+
+ LoadHolder(View itemView) {
+ super(itemView);
+ }
+
+ }
+
+ public void setMoreDataAvailable(boolean moreDataAvailable) {
+
+ isMoreDataAvailable = moreDataAvailable;
+
+ }
+
+ public void notifyDataChanged() {
+
+ notifyDataSetChanged();
+ isLoading = false;
+
+ }
+
+ public interface OnLoadMoreListener {
+
+ void onLoadMore();
+
+ }
+
+ public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) {
+
+ this.loadMoreListener = loadMoreListener;
+
+ }
+
+ @Override
+ public Filter getFilter() {
+ return prFilter;
+ }
+
+ private Filter prFilter = new Filter() {
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ List filteredList = new ArrayList<>();
+
+ if (constraint == null || constraint.length() == 0) {
+ filteredList.addAll(prList);
+ } else {
+ String filterPattern = constraint.toString().toLowerCase().trim();
+
+ for (PullRequests item : prList) {
+ if (item.getTitle().toLowerCase().contains(filterPattern) || item.getBody().toLowerCase().contains(filterPattern)) {
+ filteredList.add(item);
+ }
+ }
+ }
+
+ FilterResults results = new FilterResults();
+ results.values = filteredList;
+
+ return results;
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ prList.clear();
+ prList.addAll((List) results.values);
+ notifyDataSetChanged();
+ }
+ };
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/adapters/ReposListAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ReposListAdapter.java
index 2432f44d..29668264 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/ReposListAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/ReposListAdapter.java
@@ -50,6 +50,7 @@ public class ReposListAdapter extends RecyclerView.Adapter S createService(Class serviceClass, String instanceURL, Context ctx) {
+
+ final boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
+ File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
+ int cacheSize = 50 * 1024 * 1024; // 50MB
+ Cache cache = new Cache(httpCacheDirectory, cacheSize);
+
+ HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+ logging.setLevel(HttpLoggingInterceptor.Level.BODY);
+
+ OkHttpClient okHttpClient = new OkHttpClient.Builder()
+ .cache(cache)
+ //.addInterceptor(logging)
+ .addInterceptor(new Interceptor() {
+ @NonNull
+ @Override public Response intercept(@NonNull Chain chain) throws IOException {
+ Request request = chain.request();
+ if (connToInternet) {
+ request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
+ } else {
+ request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build();
+ }
+ return chain.proceed(request);
+ }
+ })
+ .build();
+
+ Retrofit.Builder builder = new Retrofit.Builder()
+ .baseUrl(instanceURL)
+ .client(okHttpClient)
+ .addConverterFactory(GsonConverterFactory.create());
+
+ Retrofit retrofit = builder.build();
+
+ return retrofit.create(serviceClass);
+
+ }
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java
index 1f3857e6..c127c63c 100644
--- a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java
+++ b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java
@@ -27,7 +27,7 @@ public class RetrofitClient {
private RetrofitClient(String instanceUrl, Context ctx) {
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
- int cacheSize = 20 * 1024 * 1024;
+ int cacheSize = 50 * 1024 * 1024; // 50MB
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
Cache cache = new Cache(httpCacheDirectory, cacheSize);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/ClosedIssuesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ClosedIssuesFragment.java
index 30b8cbb5..895c8940 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/ClosedIssuesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/ClosedIssuesFragment.java
@@ -28,7 +28,6 @@ import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -120,10 +119,7 @@ public class ClosedIssuesFragment extends Fragment {
}
});
- DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerViewClosed.getContext(),
- DividerItemDecoration.VERTICAL);
recyclerViewClosed.setHasFixedSize(true);
- recyclerViewClosed.addItemDecoration(dividerItemDecoration);
recyclerViewClosed.setLayoutManager(new LinearLayoutManager(context));
recyclerViewClosed.setAdapter(adapterClosed);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
index cc47dc9f..60230f18 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
@@ -5,7 +5,6 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -119,10 +118,7 @@ public class IssuesFragment extends Fragment {
}
});
- DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
- DividerItemDecoration.VERTICAL);
recyclerView.setHasFixedSize(true);
- recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(adapter);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/PullRequestsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/PullRequestsFragment.java
new file mode 100644
index 00000000..a7f868d8
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/PullRequestsFragment.java
@@ -0,0 +1,293 @@
+package org.mian.gitnex.fragments;
+
+import android.content.Context;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import android.os.Handler;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import org.mian.gitnex.R;
+import org.mian.gitnex.adapters.PullRequestsAdapter;
+import org.mian.gitnex.clients.PullRequestsService;
+import org.mian.gitnex.helpers.Authorization;
+import org.mian.gitnex.helpers.Toasty;
+import org.mian.gitnex.interfaces.ApiInterface;
+import org.mian.gitnex.models.PullRequests;
+import org.mian.gitnex.util.AppUtil;
+import org.mian.gitnex.util.TinyDB;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Author M M Arif
+ */
+
+public class PullRequestsFragment extends Fragment {
+
+ private ProgressBar mProgressBar;
+ private RecyclerView recyclerView;
+ private List prList;
+ private PullRequestsAdapter adapter;
+ private ApiInterface apiPR;
+ private String TAG = "PullRequestsListFragment - ";
+ private Context context;
+ private int pageSize = 1;
+ private TextView noData;
+ private String prState = "open";
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+
+ final View v = inflater.inflate(R.layout.fragment_pull_requests, container, false);
+ setHasOptionsMenu(true);
+
+ TinyDB tinyDb = new TinyDB(getContext());
+ String repoFullName = tinyDb.getString("repoFullName");
+ //Log.i("repoFullName", tinyDb.getString("repoFullName"));
+ String[] parts = repoFullName.split("/");
+ final String repoOwner = parts[0];
+ final String repoName = parts[1];
+ final String instanceUrl = tinyDb.getString("instanceUrl");
+ final String loginUid = tinyDb.getString("loginUid");
+ final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+
+ final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
+
+ context = getContext();
+ recyclerView = v.findViewById(R.id.recyclerView);
+ prList = new ArrayList<>();
+
+ mProgressBar = v.findViewById(R.id.progress_bar);
+ noData = v.findViewById(R.id.noData);
+
+ swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+
+ swipeRefresh.setRefreshing(false);
+ loadInitial(instanceToken, repoOwner, repoName, pageSize, prState);
+ adapter.notifyDataChanged();
+
+ }
+ }, 200);
+ }
+ });
+
+ adapter = new PullRequestsAdapter(getContext(), prList);
+ adapter.setLoadMoreListener(new PullRequestsAdapter.OnLoadMoreListener() {
+ @Override
+ public void onLoadMore() {
+
+ recyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ if(prList.size() == 10 || pageSize == 10) {
+
+ int page = (prList.size() + 10) / 10;
+ loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, prState);
+
+ }
+ /*else {
+
+ Toasty.info(context, getString(R.string.noMoreData));
+
+ }*/
+ }
+ });
+
+ }
+ });
+
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
+ DividerItemDecoration.VERTICAL);
+ recyclerView.setHasFixedSize(true);
+ recyclerView.addItemDecoration(dividerItemDecoration);
+ recyclerView.setLayoutManager(new LinearLayoutManager(context));
+ recyclerView.setAdapter(adapter);
+
+ apiPR = PullRequestsService.createService(ApiInterface.class, instanceUrl, getContext());
+ loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, pageSize, prState);
+
+ return v;
+
+ }
+
+ @Override
+ public void onResume() {
+
+ super.onResume();
+ TinyDB tinyDb = new TinyDB(getContext());
+ final String loginUid = tinyDb.getString("loginUid");
+ String repoFullName = tinyDb.getString("repoFullName");
+ String[] parts = repoFullName.split("/");
+ final String repoOwner = parts[0];
+ final String repoName = parts[1];
+ final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+
+ if(tinyDb.getBoolean("resumePullRequests")) {
+
+ loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, pageSize, prState);
+ tinyDb.putBoolean("resumePullRequests", false);
+
+ }
+
+ }
+
+ private void loadInitial(String token, String repoOwner, String repoName, int page, String prState) {
+
+ Call> call = apiPR.getPullRequests(token, repoOwner, repoName, page, prState);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull Response> response) {
+
+ if(response.isSuccessful()) {
+
+ assert response.body() != null;
+ if(response.body().size() > 0) {
+
+ prList.clear();
+ prList.addAll(response.body());
+ adapter.notifyDataChanged();
+ noData.setVisibility(View.GONE);
+
+ }
+ else {
+ prList.clear();
+ adapter.notifyDataChanged();
+ noData.setVisibility(View.VISIBLE);
+ }
+ mProgressBar.setVisibility(View.GONE);
+ }
+ else {
+ Log.i(TAG, String.valueOf(response.code()));
+ }
+
+ Log.i("http", String.valueOf(response.code()));
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+ Log.e(TAG, t.toString());
+ }
+
+ });
+
+ }
+
+ private void loadMore(String token, String repoOwner, String repoName, int page, String prState){
+
+ //add loading progress view
+ prList.add(new PullRequests("load"));
+ adapter.notifyItemInserted((prList.size() - 1));
+
+ Call> call = apiPR.getPullRequests(token, repoOwner, repoName, page, prState);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull Response> response) {
+
+ if(response.isSuccessful()){
+
+ //remove loading view
+ prList.remove(prList.size()-1);
+
+ List result = response.body();
+
+ assert result != null;
+ if(result.size() > 0) {
+
+ pageSize = result.size();
+ prList.addAll(result);
+
+ }
+ else {
+
+ Toasty.info(context, getString(R.string.noMoreData));
+ adapter.setMoreDataAvailable(false);
+
+ }
+
+ adapter.notifyDataChanged();
+
+ }
+ else {
+
+ Log.e(TAG, String.valueOf(response.code()));
+
+ }
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+
+ Log.e(TAG, t.toString());
+
+ }
+
+ });
+ }
+
+ @Override
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
+
+ boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext()));
+
+ inflater.inflate(R.menu.search_menu, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
+ searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ //searchView.setQueryHint(getContext().getString(R.string.strFilter));
+
+ /*if(!connToInternet) {
+ return;
+ }*/
+
+ searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
+
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+
+ adapter.getFilter().filter(newText);
+ return false;
+
+ }
+
+ });
+
+ }
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/SingleIssueBottomSheetFragment.java b/app/src/main/java/org/mian/gitnex/fragments/SingleIssueBottomSheetFragment.java
index 872d8027..3e4016b2 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/SingleIssueBottomSheetFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/SingleIssueBottomSheetFragment.java
@@ -12,6 +12,7 @@ import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.activities.AddRemoveAssigneesActivity;
import org.mian.gitnex.activities.AddRemoveLabelsActivity;
import org.mian.gitnex.activities.EditIssueActivity;
+import org.mian.gitnex.activities.FileDiffActivity;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
@@ -42,6 +43,7 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
TextView reOpenIssue = v.findViewById(R.id.reOpenIssue);
TextView addRemoveAssignees = v.findViewById(R.id.addRemoveAssignees);
TextView copyIssueUrl = v.findViewById(R.id.copyIssueUrl);
+ TextView openFilesDiff = v.findViewById(R.id.openFilesDiff);
replyToIssue.setOnClickListener(new View.OnClickListener() {
@Override
@@ -53,6 +55,26 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
}
});
+ if(tinyDB.getString("issueType").equals("pr")) {
+ editIssue.setText(R.string.editPrText);
+ copyIssueUrl.setText(R.string.copyPrUrlText);
+
+ if(tinyDB.getString("repoType").equals("public")) {
+ openFilesDiff.setVisibility(View.VISIBLE);
+ }
+
+ }
+
+ openFilesDiff.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ startActivity(new Intent(getContext(), FileDiffActivity.class));
+ dismiss();
+
+ }
+ });
+
editIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -90,7 +112,7 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
// get url of repo
String repoFullName = tinyDB.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDB.getString("instanceUrlRaw");
- if(!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
+ if (!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDB.getString("instanceUrlWithProtocol");
}
@@ -100,6 +122,7 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
// copy to clipboard
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(getContext()).getSystemService(android.content.Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("issueUrl", issueUrl);
+ assert clipboard != null;
clipboard.setPrimaryClip(clip);
dismiss();
@@ -109,35 +132,44 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
}
});
- if(tinyDB.getString("issueState").equals("open")) { // close issue
+ if(tinyDB.getString("issueType").equals("issue")) {
- reOpenIssue.setVisibility(View.GONE);
+ if (tinyDB.getString("issueState").equals("open")) { // close issue
- closeIssue.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
+ reOpenIssue.setVisibility(View.GONE);
- IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "closed");
- dismiss();
+ closeIssue.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
- }
- });
+ IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "closed");
+ dismiss();
+
+ }
+ });
+
+ } else if (tinyDB.getString("issueState").equals("closed")) {
+
+ closeIssue.setVisibility(View.GONE);
+
+ reOpenIssue.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "open");
+ dismiss();
+
+ }
+ });
+
+ }
}
- else if(tinyDB.getString("issueState").equals("closed")) {
+ else {
+ reOpenIssue.setVisibility(View.GONE);
closeIssue.setVisibility(View.GONE);
- reOpenIssue.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-
- IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "open");
- dismiss();
-
- }
- });
-
}
return v;
diff --git a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
index 5fe3e52a..61bd89a2 100644
--- a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
+++ b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
@@ -6,6 +6,7 @@ import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.ExploreRepositories;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.models.NewFile;
+import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UpdateIssueAssignee;
import org.mian.gitnex.models.UpdateIssueState;
import org.mian.gitnex.models.Collaborators;
@@ -30,6 +31,8 @@ import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.models.WatchRepository;
import java.util.List;
+
+import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
@@ -247,4 +250,11 @@ public interface ApiInterface {
@DELETE("repos/{owner}/{repo}/subscription") // un watch a repository
Call unWatchRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
+
+ @GET("repos/{owner}/{repo}/pulls") // get repository pull requests
+ Call> getPullRequests(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("state") String state);
+
+ @GET("{owner}/{repo}/pulls/{filename}") // get pull diff file contents
+ Call getFileDiffContents(@Path("owner") String owner, @Path("repo") String repo, @Path("filename") String fileName);
+
}
diff --git a/app/src/main/java/org/mian/gitnex/models/FileDiffView.java b/app/src/main/java/org/mian/gitnex/models/FileDiffView.java
new file mode 100644
index 00000000..bee37451
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/models/FileDiffView.java
@@ -0,0 +1,39 @@
+package org.mian.gitnex.models;
+
+/**
+ * Author M M Arif
+ */
+
+public class FileDiffView {
+
+ private String fileName;
+ private boolean fileType;
+ private String fileInfo;
+ private String fileContents;
+
+ public FileDiffView(String fileName, boolean fileType, String fileInfo, String fileContents)
+ {
+
+ this.fileName = fileName;
+ this.fileType = fileType;
+ this.fileInfo = fileInfo;
+ this.fileContents = fileContents;
+
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public boolean isFileType() {
+ return fileType;
+ }
+
+ public String getFileInfo() {
+ return fileInfo;
+ }
+
+ public String getFileContents() {
+ return fileContents;
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/models/Issues.java b/app/src/main/java/org/mian/gitnex/models/Issues.java
index 4cf00858..234242b7 100644
--- a/app/src/main/java/org/mian/gitnex/models/Issues.java
+++ b/app/src/main/java/org/mian/gitnex/models/Issues.java
@@ -98,10 +98,10 @@ public class Issues {
public class pullRequestObject {
- private String merged;
+ private boolean merged;
private String merged_at;
- public String getMerged() {
+ public boolean isMerged() {
return merged;
}
diff --git a/app/src/main/java/org/mian/gitnex/models/PullRequests.java b/app/src/main/java/org/mian/gitnex/models/PullRequests.java
new file mode 100644
index 00000000..9b479551
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/models/PullRequests.java
@@ -0,0 +1,823 @@
+package org.mian.gitnex.models;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Author M M Arif
+ */
+
+public class PullRequests {
+
+ private int id;
+ private String body;
+ private int comments;
+ private String diff_url;
+ private String html_url;
+ private String merge_base;
+ private String merge_commit_sha;
+ private boolean mergeable;
+ private boolean merged;
+ private int number;
+ private String patch_url;
+ private String state;
+ private String title;
+ private String url;
+ private Date closed_at;
+ private Date created_at;
+ private Date due_date;
+ private Date merged_at;
+ private Date updated_at;
+
+ private userObject user;
+ private List labels;
+ private List assignees;
+ private mergedByObject merged_by;
+ private milestoneObject milestone;
+ private baseObject base;
+ private headObject head;
+
+ public PullRequests(String body) {
+ this.body = body;
+ }
+
+ public class headObject {
+
+ private int repo_id;
+ private String label;
+ private String ref;
+ private String sha;
+
+ private repoObject repo;
+
+ public class repoObject {
+
+ private int repo_id;
+ private boolean allow_merge_commits;
+ private boolean allow_rebase;
+ private boolean allow_rebase_explicit;
+ private boolean allow_squash_merge;
+ private boolean archived;
+ private boolean empty;
+ private boolean fork;
+ private boolean has_issues;
+ private boolean has_pull_requests;
+ private boolean has_wiki;
+ private boolean ignore_whitespace_conflicts;
+ @SerializedName("private")
+ private boolean privateFlag;
+ private boolean mirror;
+ private String avatar_url;
+ private String clone_url;
+ private String default_branch;
+ private String description;
+ private String full_name;
+ private String html_url;
+ private String name;
+ private String ssh_url;
+ private String website;
+ private int forks_count;
+ private int id;
+ private int open_issues_count;
+ private int size;
+ private int stars_count;
+ private int watchers_count;
+ private Date created_at;
+ private Date updated_at;
+
+ private ownerObject owner;
+ private permissionsObject permissions;
+
+ public class ownerObject {
+
+ private int repo_id;
+ private boolean is_admin;
+ private String avatar_url;
+ private String email;
+ private String full_name;
+ private String language;
+ private String login;
+ private Date created;
+
+ public int getRepo_id() {
+ return repo_id;
+ }
+
+ public boolean isIs_admin() {
+ return is_admin;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+ }
+
+ public class permissionsObject {
+
+ private boolean admin;
+ private boolean pull;
+ private boolean push;
+
+ public boolean isAdmin() {
+ return admin;
+ }
+
+ public boolean isPull() {
+ return pull;
+ }
+
+ public boolean isPush() {
+ return push;
+ }
+ }
+
+ public int getRepo_id() {
+ return repo_id;
+ }
+
+ public boolean isAllow_merge_commits() {
+ return allow_merge_commits;
+ }
+
+ public boolean isAllow_rebase() {
+ return allow_rebase;
+ }
+
+ public boolean isAllow_rebase_explicit() {
+ return allow_rebase_explicit;
+ }
+
+ public boolean isAllow_squash_merge() {
+ return allow_squash_merge;
+ }
+
+ public boolean isArchived() {
+ return archived;
+ }
+
+ public boolean isEmpty() {
+ return empty;
+ }
+
+ public boolean isFork() {
+ return fork;
+ }
+
+ public boolean isHas_issues() {
+ return has_issues;
+ }
+
+ public boolean isHas_pull_requests() {
+ return has_pull_requests;
+ }
+
+ public boolean isHas_wiki() {
+ return has_wiki;
+ }
+
+ public boolean isIgnore_whitespace_conflicts() {
+ return ignore_whitespace_conflicts;
+ }
+
+ public boolean isPrivateFlag() {
+ return privateFlag;
+ }
+
+ public boolean isMirror() {
+ return mirror;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getClone_url() {
+ return clone_url;
+ }
+
+ public String getDefault_branch() {
+ return default_branch;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getHtml_url() {
+ return html_url;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSsh_url() {
+ return ssh_url;
+ }
+
+ public String getWebsite() {
+ return website;
+ }
+
+ public int getForks_count() {
+ return forks_count;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public int getOpen_issues_count() {
+ return open_issues_count;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int getStars_count() {
+ return stars_count;
+ }
+
+ public int getWatchers_count() {
+ return watchers_count;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public Date getUpdated_at() {
+ return updated_at;
+ }
+
+ public ownerObject getOwner() {
+ return owner;
+ }
+
+ public permissionsObject getPermissions() {
+ return permissions;
+ }
+ }
+
+ }
+
+ public class baseObject {
+
+ private int repo_id;
+ private String label;
+ private String ref;
+ private String sha;
+
+ private repoObject repo;
+
+ public class repoObject {
+
+ private int repo_id;
+ private boolean allow_merge_commits;
+ private boolean allow_rebase;
+ private boolean allow_rebase_explicit;
+ private boolean allow_squash_merge;
+ private boolean archived;
+ private boolean empty;
+ private boolean fork;
+ private boolean has_issues;
+ private boolean has_pull_requests;
+ private boolean has_wiki;
+ private boolean ignore_whitespace_conflicts;
+ @SerializedName("private")
+ private boolean privateFlag;
+ private boolean mirror;
+ private String avatar_url;
+ private String clone_url;
+ private String default_branch;
+ private String description;
+ private String full_name;
+ private String html_url;
+ private String name;
+ private String ssh_url;
+ private String website;
+ private int forks_count;
+ private int id;
+ private int open_issues_count;
+ private int size;
+ private int stars_count;
+ private int watchers_count;
+ private Date created_at;
+ private Date updated_at;
+
+ private ownerObject owner;
+ private permissionsObject permissions;
+
+ public class ownerObject {
+
+ private int repo_id;
+ private boolean is_admin;
+ private String avatar_url;
+ private String email;
+ private String full_name;
+ private String language;
+ private String login;
+ private Date created;
+
+ public int getRepo_id() {
+ return repo_id;
+ }
+
+ public boolean isIs_admin() {
+ return is_admin;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+ }
+
+ public class permissionsObject {
+
+ private boolean admin;
+ private boolean pull;
+ private boolean push;
+
+ public boolean isAdmin() {
+ return admin;
+ }
+
+ public boolean isPull() {
+ return pull;
+ }
+
+ public boolean isPush() {
+ return push;
+ }
+ }
+
+ public int getRepo_id() {
+ return repo_id;
+ }
+
+ public boolean isAllow_merge_commits() {
+ return allow_merge_commits;
+ }
+
+ public boolean isAllow_rebase() {
+ return allow_rebase;
+ }
+
+ public boolean isAllow_rebase_explicit() {
+ return allow_rebase_explicit;
+ }
+
+ public boolean isAllow_squash_merge() {
+ return allow_squash_merge;
+ }
+
+ public boolean isArchived() {
+ return archived;
+ }
+
+ public boolean isEmpty() {
+ return empty;
+ }
+
+ public boolean isFork() {
+ return fork;
+ }
+
+ public boolean isHas_issues() {
+ return has_issues;
+ }
+
+ public boolean isHas_pull_requests() {
+ return has_pull_requests;
+ }
+
+ public boolean isHas_wiki() {
+ return has_wiki;
+ }
+
+ public boolean isIgnore_whitespace_conflicts() {
+ return ignore_whitespace_conflicts;
+ }
+
+ public boolean isPrivateFlag() {
+ return privateFlag;
+ }
+
+ public boolean isMirror() {
+ return mirror;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getClone_url() {
+ return clone_url;
+ }
+
+ public String getDefault_branch() {
+ return default_branch;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getHtml_url() {
+ return html_url;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSsh_url() {
+ return ssh_url;
+ }
+
+ public String getWebsite() {
+ return website;
+ }
+
+ public int getForks_count() {
+ return forks_count;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public int getOpen_issues_count() {
+ return open_issues_count;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int getStars_count() {
+ return stars_count;
+ }
+
+ public int getWatchers_count() {
+ return watchers_count;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public Date getUpdated_at() {
+ return updated_at;
+ }
+
+ public ownerObject getOwner() {
+ return owner;
+ }
+
+ public permissionsObject getPermissions() {
+ return permissions;
+ }
+ }
+
+ }
+
+ public class userObject {
+
+ private int id;
+ private String login;
+ private String full_name;
+ private String email;
+ private String avatar_url;
+ private String language;
+ private boolean is_admin;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public boolean isIs_admin() {
+ return is_admin;
+ }
+ }
+
+ public class labelsObject {
+
+ private int id;
+ private String name;
+ private String color;
+ private String url;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+ }
+
+ public class assigneesObject {
+
+ private int id;
+ private String login;
+ private String full_name;
+ private String email;
+ private String avatar_url;
+ private String language;
+ private boolean is_admin;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public boolean isIs_admin() {
+ return is_admin;
+ }
+ }
+
+ public class mergedByObject {
+
+ private int id;
+ private String login;
+ private String full_name;
+ private String email;
+ private String avatar_url;
+ private String language;
+ private boolean is_admin;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public boolean isIs_admin() {
+ return is_admin;
+ }
+ }
+
+ public class milestoneObject {
+
+ private int id;
+ private String title;
+ private String description;
+ private String state;
+ private String open_issues;
+ private String closed_issues;
+ private String closed_at;
+ private String due_on;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public String getOpen_issues() {
+ return open_issues;
+ }
+
+ public String getClosed_issues() {
+ return closed_issues;
+ }
+
+ public String getClosed_at() {
+ return closed_at;
+ }
+
+ public String getDue_on() {
+ return due_on;
+ }
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public int getComments() {
+ return comments;
+ }
+
+ public String getDiff_url() {
+ return diff_url;
+ }
+
+ public String getHtml_url() {
+ return html_url;
+ }
+
+ public String getMerge_base() {
+ return merge_base;
+ }
+
+ public String getMerge_commit_sha() {
+ return merge_commit_sha;
+ }
+
+ public boolean isMergeable() {
+ return mergeable;
+ }
+
+ public boolean isMerged() {
+ return merged;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public String getPatch_url() {
+ return patch_url;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public Date getClosed_at() {
+ return closed_at;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public Date getDue_date() {
+ return due_date;
+ }
+
+ public Date getMerged_at() {
+ return merged_at;
+ }
+
+ public Date getUpdated_at() {
+ return updated_at;
+ }
+
+ public userObject getUser() {
+ return user;
+ }
+
+ public List getLabels() {
+ return labels;
+ }
+
+ public List getAssignees() {
+ return assignees;
+ }
+
+ public mergedByObject getMerged_by() {
+ return merged_by;
+ }
+
+ public milestoneObject getMilestone() {
+ return milestone;
+ }
+
+ public baseObject getBase() {
+ return base;
+ }
+
+ public headObject getHead() {
+ return head;
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/util/AppUtil.java b/app/src/main/java/org/mian/gitnex/util/AppUtil.java
index 7fee1811..4c7ee546 100644
--- a/app/src/main/java/org/mian/gitnex/util/AppUtil.java
+++ b/app/src/main/java/org/mian/gitnex/util/AppUtil.java
@@ -217,7 +217,8 @@ public class AppUtil {
"cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript",
"coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt",
"ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs",
- "vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js"};
+ "vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js",
+ "html", "htm", "volt", "ini", "htaccess", "conf", "gitignore"};
return Arrays.asList(extValues).contains(ext);
diff --git a/app/src/main/res/layout/activity_file_diff.xml b/app/src/main/res/layout/activity_file_diff.xml
new file mode 100644
index 00000000..af6d9e2b
--- /dev/null
+++ b/app/src/main/res/layout/activity_file_diff.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_repo_detail.xml b/app/src/main/res/layout/activity_repo_detail.xml
index 2e4123b1..c2a660b7 100644
--- a/app/src/main/res/layout/activity_repo_detail.xml
+++ b/app/src/main/res/layout/activity_repo_detail.xml
@@ -57,6 +57,12 @@
android:layout_height="wrap_content"
android:text="@string/tabItemCloseIssues" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_pull_requests.xml b/app/src/main/res/layout/fragment_pull_requests.xml
new file mode 100644
index 00000000..87ba9c16
--- /dev/null
+++ b/app/src/main/res/layout/fragment_pull_requests.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/my_repos_list.xml b/app/src/main/res/layout/my_repos_list.xml
index 2a281252..6a76758b 100644
--- a/app/src/main/res/layout/my_repos_list.xml
+++ b/app/src/main/res/layout/my_repos_list.xml
@@ -4,6 +4,12 @@
android:layout_height="wrap_content"
android:background="@color/backgroundColor" >
+
+
@@ -39,28 +41,14 @@
-
-
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/repo_pr_list.xml b/app/src/main/res/layout/repo_pr_list.xml
new file mode 100644
index 00000000..331a2b24
--- /dev/null
+++ b/app/src/main/res/layout/repo_pr_list.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/repos_list.xml b/app/src/main/res/layout/repos_list.xml
index 5c76207d..8aa5ea25 100644
--- a/app/src/main/res/layout/repos_list.xml
+++ b/app/src/main/res/layout/repos_list.xml
@@ -4,6 +4,12 @@
android:layout_height="wrap_content"
android:background="@color/backgroundColor" >
+
+
+
+
+
+
-
+
+
#e74c3c
#3faef7
#b6bbbf
+ #368f73
+ #63fdd9
+ #ffe0e0
+ #d6fcd6
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 275aa2de..ebb157d4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,7 +13,7 @@
https://liberapay.com/mmarif/donate
https://www.patreon.com/mmarif
%1$s / build %2$d
- GitNex is a free, open-source Android client for Git repository management tool Gitea. GitNex is Licensed under GPLv3.\n\nThanks to all the contributors and sponsors for your generous work and donations.
+ GitNex is a free, open-source Android client for Git repository management tool Gitea. GitNex is Licensed under GPLv3.\n\nThanks to all the contributors and donators for your generous work and donations.
https://crowdin.com/project/gitnex
Report issues at Gitea
@@ -52,7 +52,7 @@
New Label
Credits
Update Label
- Sponsors
+ Donators
Starred Repositories
New Team
Add Email Address
@@ -143,6 +143,7 @@
Labels
Settings
Collaborators
+ Pull Requests
No issues found
@@ -406,7 +407,7 @@
Edit Issue #%1$s
- Issue updated.
+ Issue updated
@@ -459,7 +460,7 @@
Filter
Copy Issue URL
- Issue URL copied to clipboard
+ URL copied to clipboard
%1$d\uFF05 completed
@@ -495,6 +496,9 @@
All fields are required
Continue
Token
+ -
+ private
+ public
Translate GitNex with Crowdin
@@ -523,4 +527,15 @@
Instance has returned an error - Unauthorized. Check your credentials and try again
Please enter the correct token
+ No pull requests found
+ Creator :\u0020
+ Edit Pull Request
+ Copy Pull Request URL
+ Edit Pull Request #%1$s
+ Pull Request updated
+ %1$s Files Changed
+ %1$s File Changed
+ -%1$s
+ Files Changed
+