Merge branch '10-merge-pr' of gitnex/GitNex into master

This commit is contained in:
M M Arif 2019-11-27 17:03:49 +00:00
commit a32e11c172
9 changed files with 448 additions and 6 deletions

View File

@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mian.gitnex"> package="org.mian.gitnex">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/app_logo" android:icon="@mipmap/app_logo"
@ -10,9 +13,10 @@
android:roundIcon="@mipmap/app_logo_round" android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity android:name=".activities.MergePullRequestActivity"></activity>
<activity <activity
android:name=".activities.FileViewActivity" android:name=".activities.FileViewActivity"
android:theme="@style/AppTheme.NoActionBar"></activity> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.NewFileActivity" android:name=".activities.NewFileActivity"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
@ -68,7 +72,5 @@
<activity android:name=".activities.OpenRepoInBrowserActivity" /> <activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" /> <activity android:name=".activities.FileDiffActivity" />
</application> </application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest> </manifest>

View File

@ -0,0 +1,258 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class MergePullRequestActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private SocialAutoCompleteTextView mergePR;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button mergeButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_merge_pull_request);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
mergePR = findViewById(R.id.mergePR);
mergePR.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
mergePR.setMentionAdapter(defaultMentionAdapter);
closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mergeButton = findViewById(R.id.mergeButton);
if(!connToInternet) {
disableProcessButton();
} else {
mergeButton.setOnClickListener(mergePullRequest);
}
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
}
else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private View.OnClickListener mergePullRequest = new View.OnClickListener() {
public void onClick(View v) {
processMergePullRequest();
}
};
private void processMergePullRequest() {
String mergePRDT = mergePR.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
disableProcessButton();
String doWhat = "merge";
mergeFunction(doWhat, mergePRDT);
}
private void mergeFunction(String doWhat, String mergePRDT) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
MergePullRequest mergePR = new MergePullRequest(doWhat, mergePRDT, null);
Call<ResponseBody> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.mergePullRequest(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
if(response.code() == 200) {
Toasty.info(getApplicationContext(), getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.mergePR404ErrorMsg));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
mergeButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
mergeButton.setBackground(shape);
}
private void enableProcessButton() {
mergeButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
mergeButton.setBackground(shape);
}
}

View File

@ -260,7 +260,7 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
MenuItem searchItem = menu.findItem(R.id.action_search); MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView(); androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE); searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter)); //searchView.setQueryHint(getContext().getString(R.string.search));
/*if(!connToInternet) { /*if(!connToInternet) {
return; return;

View File

@ -13,6 +13,7 @@ import org.mian.gitnex.activities.AddRemoveAssigneesActivity;
import org.mian.gitnex.activities.AddRemoveLabelsActivity; import org.mian.gitnex.activities.AddRemoveLabelsActivity;
import org.mian.gitnex.activities.EditIssueActivity; import org.mian.gitnex.activities.EditIssueActivity;
import org.mian.gitnex.activities.FileDiffActivity; import org.mian.gitnex.activities.FileDiffActivity;
import org.mian.gitnex.activities.MergePullRequestActivity;
import org.mian.gitnex.activities.ReplyToIssueActivity; import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
@ -44,6 +45,7 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
TextView addRemoveAssignees = v.findViewById(R.id.addRemoveAssignees); TextView addRemoveAssignees = v.findViewById(R.id.addRemoveAssignees);
TextView copyIssueUrl = v.findViewById(R.id.copyIssueUrl); TextView copyIssueUrl = v.findViewById(R.id.copyIssueUrl);
TextView openFilesDiff = v.findViewById(R.id.openFilesDiff); TextView openFilesDiff = v.findViewById(R.id.openFilesDiff);
TextView mergePullRequest = v.findViewById(R.id.mergePullRequest);
replyToIssue.setOnClickListener(new View.OnClickListener() { replyToIssue.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -56,14 +58,40 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
}); });
if(tinyDB.getString("issueType").equals("pr")) { if(tinyDB.getString("issueType").equals("pr")) {
editIssue.setText(R.string.editPrText); editIssue.setText(R.string.editPrText);
copyIssueUrl.setText(R.string.copyPrUrlText); copyIssueUrl.setText(R.string.copyPrUrlText);
if(tinyDB.getBoolean("prMerged")) {
mergePullRequest.setVisibility(View.GONE);
}
else {
mergePullRequest.setVisibility(View.VISIBLE);
}
if(tinyDB.getString("repoType").equals("public")) { if(tinyDB.getString("repoType").equals("public")) {
openFilesDiff.setVisibility(View.VISIBLE); openFilesDiff.setVisibility(View.VISIBLE);
} }
else {
openFilesDiff.setVisibility(View.GONE);
}
} }
else {
mergePullRequest.setVisibility(View.GONE);
}
mergePullRequest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), MergePullRequestActivity.class));
dismiss();
}
});
openFilesDiff.setOnClickListener(new View.OnClickListener() { openFilesDiff.setOnClickListener(new View.OnClickListener() {
@Override @Override

View File

@ -5,6 +5,7 @@ import org.mian.gitnex.models.AddEmail;
import org.mian.gitnex.models.Branches; import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.ExploreRepositories; import org.mian.gitnex.models.ExploreRepositories;
import org.mian.gitnex.models.Files; import org.mian.gitnex.models.Files;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.NewFile; import org.mian.gitnex.models.NewFile;
import org.mian.gitnex.models.PullRequests; import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UpdateIssueAssignee; import org.mian.gitnex.models.UpdateIssueAssignee;
@ -31,7 +32,6 @@ import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserTokens; import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.models.WatchRepository; import org.mian.gitnex.models.WatchRepository;
import java.util.List; import java.util.List;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.http.Body; import retrofit2.http.Body;
@ -257,4 +257,6 @@ public interface ApiInterface {
@GET("{owner}/{repo}/pulls/{filename}") // get pull diff file contents @GET("{owner}/{repo}/pulls/{filename}") // get pull diff file contents
Call<ResponseBody> getFileDiffContents(@Path("owner") String owner, @Path("repo") String repo, @Path("filename") String fileName); Call<ResponseBody> getFileDiffContents(@Path("owner") String owner, @Path("repo") String repo, @Path("filename") String fileName);
@POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request
Call<ResponseBody> mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr);
} }

View File

@ -0,0 +1,19 @@
package org.mian.gitnex.models;
/**
* Author M M Arif
*/
public class MergePullRequest {
private String Do;
private String MergeMessageField;
private String MergeTitleField;
public MergePullRequest(String Do, String MergeMessageField, String MergeTitleField) {
this.Do = Do;
this.MergeMessageField = MergeMessageField;
this.MergeTitleField = MergeTitleField;
}
}

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/colorPrimary">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
tools:ignore="UnusedAttribute">
<ImageView
android:id="@+id/close"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="15dp"
android:layout_marginLeft="15dp"
android:gravity="center_vertical"
android:contentDescription="@string/close"
android:src="@drawable/ic_close" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/replyToPRNavHeader"
android:foregroundGravity="right"
android:layout_marginEnd="25dp"
android:layout_marginStart="0dp"
android:scrollbarThumbHorizontal="@android:color/transparent"
android:fillViewport="true">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="@color/white"
android:maxLines="1"
android:textSize="20sp" />
</HorizontalScrollView>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/backgroundColor">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:paddingBottom="30dp"
android:orientation="vertical">
<com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView
android:id="@+id/mergePR"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:completionThreshold="1"
android:background="@drawable/shape_inputs"
android:maxLines="12"
android:minLines="10"
tools:ignore="Autofill"
android:labelFor="@+id/mergePR"
android:scrollbars="vertical"
android:gravity="top|start"
android:textSize="14sp"
android:textColor="@color/white"
android:hint="@string/mergeCommentText"
android:textColorHint="@color/colorAccent"
android:inputType="textCapSentences|textMultiLine"
android:textColorHighlight="@color/white" />
<TextView
android:id="@+id/mergeInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/mergeNoteText"
android:textColor="@color/hintColor"
android:textSize="12sp"
android:gravity="start"
android:layout_marginTop="10dp" />
<Button
android:id="@+id/mergeButton"
android:gravity="center"
android:layout_gravity="end"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:text="@string/mergePullRequestButtonText"
android:background="@drawable/shape_buttons"
android:textColor="@color/btnTextColor" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -42,6 +42,18 @@
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="16dp" />
<TextView
android:id="@+id/mergePullRequest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/mergePullRequestText"
android:drawableStart="@drawable/ic_merge"
android:drawablePadding="24dp"
android:textColor="@color/white"
android:textSize="16sp"
android:padding="16dp" />
<TextView <TextView
android:id="@+id/editIssue" android:id="@+id/editIssue"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -534,5 +534,11 @@
<string name="fileDiffViewHeaderSingle">%1$s File Changed</string> <string name="fileDiffViewHeaderSingle">%1$s File Changed</string>
<string name="fileDiffInfoChanges" translatable="false">-%1$s</string> <string name="fileDiffInfoChanges" translatable="false">-%1$s</string>
<string name="openFileDiffText">Files Changed</string> <string name="openFileDiffText">Files Changed</string>
<string name="mergePullRequestText">Merge Pull Request</string>
<string name="mergePullRequestButtonText">Merge</string>
<string name="mergeNoteText">Merge may fail if you are not authorized to merge this Pull Request.</string>
<string name="mergeCommentText">Merge comment</string>
<string name="mergePRSuccessMsg">Pull Request was merged successfully</string>
<string name="mergePR404ErrorMsg">Pull Request is not available for merge</string>
</resources> </resources>