mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2023-12-13 20:50:18 +01:00
Extend CI workflows (-> https://codeberg.org/gitnex/GitNex/issues/1099) 1. pull translations and push them again on every pull @mmarif this needs the secrets and `BOT_TOKEN` the code for this comes from tea4j-autodeploy 2. add a **template** for a check workflow which only does some static checks right now. It is disabled because it requires some investigation and discussion on how we should deal with these issues. The checks are currently (if we would enable it): 1. check code style and formatting according to the project file in `.idea/` 2. make sure every Java file has an `@author` annotation I would wait until you reviewed with enabling them because we have to reformat all the files which results in changes with a few thousand changed lines (tried this once). Closes https://codeberg.org/gitnex/GitNex/issues/141 Co-authored-by: qwerty287 <ndev@web.de> Co-authored-by: M M Arif <mmarif@noreply.codeberg.org> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1155 Reviewed-by: 6543 <6543@noreply.codeberg.org> Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org> Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
405 lines
13 KiB
Java
405 lines
13 KiB
Java
package org.mian.gitnex.activities;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.util.Log;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.TextView;
|
|
import androidx.annotation.NonNull;
|
|
import org.gitnex.tea4j.v2.models.Branch;
|
|
import org.gitnex.tea4j.v2.models.CreateFileOptions;
|
|
import org.gitnex.tea4j.v2.models.DeleteFileOptions;
|
|
import org.gitnex.tea4j.v2.models.FileDeleteResponse;
|
|
import org.gitnex.tea4j.v2.models.FileResponse;
|
|
import org.gitnex.tea4j.v2.models.UpdateFileOptions;
|
|
import org.mian.gitnex.R;
|
|
import org.mian.gitnex.clients.RetrofitClient;
|
|
import org.mian.gitnex.databinding.ActivityCreateFileBinding;
|
|
import org.mian.gitnex.helpers.AlertDialogs;
|
|
import org.mian.gitnex.helpers.AppUtil;
|
|
import org.mian.gitnex.helpers.NetworkStatusObserver;
|
|
import org.mian.gitnex.helpers.Toasty;
|
|
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import retrofit2.Call;
|
|
import retrofit2.Callback;
|
|
|
|
/**
|
|
* @author M M Arif
|
|
*/
|
|
|
|
public class CreateFileActivity extends BaseActivity {
|
|
|
|
private ActivityCreateFileBinding binding;
|
|
|
|
public static final int FILE_ACTION_CREATE = 0;
|
|
public static final int FILE_ACTION_DELETE = 1;
|
|
public static final int FILE_ACTION_EDIT = 2;
|
|
|
|
private int fileAction = FILE_ACTION_CREATE;
|
|
|
|
private String filePath;
|
|
private String fileSha;
|
|
|
|
private final List<String> branches = new ArrayList<>();
|
|
|
|
private RepositoryContext repository;
|
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
binding = ActivityCreateFileBinding.inflate(getLayoutInflater());
|
|
setContentView(binding.getRoot());
|
|
|
|
repository = RepositoryContext.fromIntent(getIntent());
|
|
|
|
TextView toolbarTitle = binding.toolbarTitle;
|
|
|
|
binding.newFileName.requestFocus();
|
|
|
|
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
assert inputMethodManager != null;
|
|
inputMethodManager.showSoftInput(binding.newFileName, InputMethodManager.SHOW_IMPLICIT);
|
|
|
|
binding.close.setOnClickListener(view -> finish());
|
|
binding.newFileContent.setOnTouchListener((touchView, motionEvent) -> {
|
|
|
|
touchView.getParent().requestDisallowInterceptTouchEvent(true);
|
|
|
|
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 &&
|
|
(motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
|
|
|
|
touchView.getParent().requestDisallowInterceptTouchEvent(false);
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE) == FILE_ACTION_DELETE) {
|
|
|
|
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE);
|
|
filePath = getIntent().getStringExtra("filePath");
|
|
fileSha = getIntent().getStringExtra("fileSha");
|
|
|
|
toolbarTitle.setText(getString(R.string.deleteGenericTitle, filePath));
|
|
|
|
binding.newFileCreate.setText(R.string.deleteFile);
|
|
|
|
binding.newFileNameLayout.setVisibility(View.GONE);
|
|
binding.newFileContentLayout.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT) == FILE_ACTION_EDIT) {
|
|
|
|
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT);
|
|
filePath = getIntent().getStringExtra("filePath");
|
|
fileSha = getIntent().getStringExtra("fileSha");
|
|
|
|
toolbarTitle.setText(getString(R.string.editFileText, filePath));
|
|
|
|
binding.newFileCreate.setText(R.string.editFile);
|
|
binding.newFileName.setText(filePath);
|
|
binding.newFileName.setEnabled(false);
|
|
binding.newFileName.setFocusable(false);
|
|
|
|
binding.newFileContent.setText(getIntent().getStringExtra("fileContents"));
|
|
|
|
}
|
|
|
|
getBranches(repository.getOwner(), repository.getName());
|
|
|
|
disableProcessButton();
|
|
|
|
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
|
|
networkStatusObserver.registerNetworkStatusListener(hasNetworkConnection -> runOnUiThread(() -> binding.newFileCreate.setEnabled(hasNetworkConnection)));
|
|
|
|
binding.newFileCreate.setOnClickListener(v -> processNewFile());
|
|
|
|
}
|
|
|
|
private void processNewFile() {
|
|
|
|
String newFileName = binding.newFileName.getText() != null ? binding.newFileName.getText().toString() : "";
|
|
String newFileContent = binding.newFileContent.getText() != null ? binding.newFileContent.getText().toString() : "";
|
|
String newFileBranchName = binding.newFileBranches.getText() != null ? binding.newFileBranches.getText().toString() : "";
|
|
String newFileCommitMessage = binding.newFileCommitMessage.getText() != null ? binding.newFileCommitMessage.getText().toString() : "";
|
|
|
|
if(!AppUtil.hasNetworkConnection(appCtx)) {
|
|
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
|
|
return;
|
|
}
|
|
|
|
if(((newFileName.isEmpty() || newFileContent.isEmpty()) && fileAction != FILE_ACTION_DELETE) || newFileCommitMessage.isEmpty()) {
|
|
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
|
|
return;
|
|
}
|
|
|
|
if(!AppUtil.checkStringsWithDash(newFileBranchName)) {
|
|
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
|
|
return;
|
|
}
|
|
|
|
if(newFileCommitMessage.length() > 255) {
|
|
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
|
|
return;
|
|
}
|
|
|
|
disableProcessButton();
|
|
|
|
switch(fileAction) {
|
|
|
|
case FILE_ACTION_CREATE:
|
|
createNewFile(repository.getOwner(), repository.getName(), newFileName, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName);
|
|
break;
|
|
|
|
case FILE_ACTION_DELETE:
|
|
deleteFile(repository.getOwner(), repository.getName(), filePath, newFileCommitMessage, newFileBranchName, fileSha);
|
|
break;
|
|
|
|
case FILE_ACTION_EDIT:
|
|
editFile(repository.getOwner(), repository.getName(), filePath, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName, fileSha);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
private void createNewFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName) {
|
|
|
|
CreateFileOptions createNewFileJsonStr = new CreateFileOptions();
|
|
createNewFileJsonStr.setContent(fileContent);
|
|
createNewFileJsonStr.setMessage(fileCommitMessage);
|
|
if(branches.contains(branchName)) {
|
|
createNewFileJsonStr.setBranch(branchName);
|
|
} else {
|
|
createNewFileJsonStr.setNewBranch(branchName);
|
|
}
|
|
|
|
Call<FileResponse> call = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.repoCreateFile(createNewFileJsonStr, repoOwner, repoName, fileName);
|
|
|
|
call.enqueue(new Callback<FileResponse>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<FileResponse> call, @NonNull retrofit2.Response<FileResponse> response) {
|
|
|
|
switch(response.code()) {
|
|
|
|
case 201:
|
|
enableProcessButton();
|
|
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
|
|
Intent result = new Intent();
|
|
result.putExtra("fileModified", true);
|
|
result.putExtra("fileAction", fileAction);
|
|
setResult(200, result);
|
|
finish();
|
|
break;
|
|
|
|
case 401:
|
|
enableProcessButton();
|
|
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
|
break;
|
|
|
|
case 404:
|
|
enableProcessButton();
|
|
Toasty.warning(ctx, getString(R.string.apiNotFound));
|
|
break;
|
|
|
|
default:
|
|
enableProcessButton();
|
|
Toasty.error(ctx, getString(R.string.genericError));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {
|
|
|
|
Log.e("onFailure", t.toString());
|
|
enableProcessButton();
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void deleteFile(String repoOwner, String repoName, String fileName, String fileCommitMessage, String branchName, String fileSha) {
|
|
|
|
DeleteFileOptions deleteFileJsonStr = new DeleteFileOptions();
|
|
deleteFileJsonStr.setMessage(fileCommitMessage);
|
|
deleteFileJsonStr.setSha(fileSha);
|
|
if(branches.contains(branchName)) {
|
|
deleteFileJsonStr.setBranch(branchName);
|
|
} else {
|
|
deleteFileJsonStr.setNewBranch(branchName);
|
|
}
|
|
|
|
Call<FileDeleteResponse> call = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.repoDeleteFileWithBody(repoOwner, repoName, fileName, deleteFileJsonStr);
|
|
|
|
call.enqueue(new Callback<FileDeleteResponse>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<FileDeleteResponse> call, @NonNull retrofit2.Response<FileDeleteResponse> response) {
|
|
|
|
switch(response.code()) {
|
|
|
|
case 200:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.deleteFileMessage, repository.getBranchRef()));
|
|
Intent result = new Intent();
|
|
result.putExtra("fileModified", true);
|
|
result.putExtra("fileAction", fileAction);
|
|
setResult(200, result);
|
|
finish();
|
|
break;
|
|
|
|
case 401:
|
|
enableProcessButton();
|
|
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
|
break;
|
|
|
|
case 404:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.apiNotFound));
|
|
break;
|
|
|
|
default:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.genericError));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<FileDeleteResponse> call, @NonNull Throwable t) {
|
|
|
|
Log.e("onFailure", t.toString());
|
|
enableProcessButton();
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void editFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName, String fileSha) {
|
|
|
|
UpdateFileOptions editFileJsonStr = new UpdateFileOptions();
|
|
editFileJsonStr.setContent(fileContent);
|
|
editFileJsonStr.setMessage(fileCommitMessage);
|
|
editFileJsonStr.setSha(fileSha);
|
|
if(branches.contains(branchName)) {
|
|
editFileJsonStr.setBranch(branchName);
|
|
} else {
|
|
editFileJsonStr.setNewBranch(branchName);
|
|
}
|
|
|
|
Call<FileResponse> call = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.repoUpdateFile(editFileJsonStr, repoOwner, repoName, fileName);
|
|
|
|
call.enqueue(new Callback<FileResponse>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<FileResponse> call, @NonNull retrofit2.Response<FileResponse> response) {
|
|
|
|
switch(response.code()) {
|
|
|
|
case 200:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
|
|
Intent result = new Intent();
|
|
result.putExtra("fileModified", true);
|
|
result.putExtra("fileAction", fileAction);
|
|
setResult(200, result);
|
|
finish();
|
|
break;
|
|
|
|
case 401:
|
|
enableProcessButton();
|
|
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
|
break;
|
|
|
|
case 404:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.apiNotFound));
|
|
break;
|
|
|
|
default:
|
|
enableProcessButton();
|
|
Toasty.info(ctx, getString(R.string.genericError));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {
|
|
|
|
Log.e("onFailure", t.toString());
|
|
enableProcessButton();
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void getBranches(String repoOwner, String repoName) {
|
|
|
|
Call<List<Branch>> call = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.repoListBranches(repoOwner, repoName, null, null);
|
|
|
|
call.enqueue(new Callback<List<Branch>>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<List<Branch>> call, @NonNull retrofit2.Response<List<Branch>> response) {
|
|
|
|
if(response.code() == 200) {
|
|
|
|
assert response.body() != null;
|
|
for(Branch branch : response.body()) branches.add(branch.getName());
|
|
|
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(CreateFileActivity.this, R.layout.list_spinner_items, branches);
|
|
|
|
binding.newFileBranches.setAdapter(adapter);
|
|
binding.newFileBranches.setText(repository.getBranchRef(), false);
|
|
|
|
enableProcessButton();
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
|
|
|
|
Log.e("onFailure", t.toString());
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void disableProcessButton() { binding.newFileCreate.setEnabled(false); }
|
|
private void enableProcessButton() { binding.newFileCreate.setEnabled(true); }
|
|
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
repository.checkAccountSwitch(this);
|
|
}
|
|
|
|
}
|