mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2023-12-13 20:50:18 +01:00
Removing file size selection dialog in favor of hardcoded value. Adding warning to file size picker and minor improvements. Bump dependencies and gradle Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition Improving credits, adding symlink and submodule icons to FilesAdapter and removing unused libraries. Minor improvements and bug fixes. Add true progress indication routine for copying streams. Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition Performance and memory usage improvements Notification improvements Renaming StaticGlobalVariables to Constants Overall improvements and fixes. Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition Add additional image formats. Adding audio and video categories. Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition Improve file type handling. Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/841 Reviewed-by: M M Arif <mmarif@noreply.codeberg.org> Co-Authored-By: opyale <opyale@noreply.codeberg.org> Co-Committed-By: opyale <opyale@noreply.codeberg.org>
383 lines
13 KiB
Java
383 lines
13 KiB
Java
package org.mian.gitnex.activities;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.app.DatePickerDialog;
|
|
import android.app.Dialog;
|
|
import android.content.Context;
|
|
import android.graphics.Color;
|
|
import android.graphics.drawable.ColorDrawable;
|
|
import android.os.Bundle;
|
|
import android.view.LayoutInflater;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.ArrayAdapter;
|
|
import androidx.annotation.NonNull;
|
|
import com.google.gson.JsonElement;
|
|
import org.gitnex.tea4j.models.Collaborators;
|
|
import org.gitnex.tea4j.models.CreateIssue;
|
|
import org.gitnex.tea4j.models.Labels;
|
|
import org.gitnex.tea4j.models.Milestones;
|
|
import org.mian.gitnex.R;
|
|
import org.mian.gitnex.actions.AssigneesActions;
|
|
import org.mian.gitnex.actions.LabelsActions;
|
|
import org.mian.gitnex.adapters.AssigneesListAdapter;
|
|
import org.mian.gitnex.adapters.LabelsListAdapter;
|
|
import org.mian.gitnex.clients.RetrofitClient;
|
|
import org.mian.gitnex.databinding.ActivityCreateIssueBinding;
|
|
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
|
|
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
|
|
import org.mian.gitnex.helpers.AlertDialogs;
|
|
import org.mian.gitnex.helpers.AppUtil;
|
|
import org.mian.gitnex.helpers.Authorization;
|
|
import org.mian.gitnex.helpers.Constants;
|
|
import org.mian.gitnex.helpers.TinyDB;
|
|
import org.mian.gitnex.helpers.Toasty;
|
|
import org.mian.gitnex.helpers.Version;
|
|
import java.util.ArrayList;
|
|
import java.util.Calendar;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import retrofit2.Call;
|
|
import retrofit2.Callback;
|
|
|
|
/**
|
|
* Author M M Arif
|
|
*/
|
|
|
|
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener, LabelsListAdapter.LabelsListAdapterListener, AssigneesListAdapter.AssigneesListAdapterListener {
|
|
|
|
private ActivityCreateIssueBinding viewBinding;
|
|
private CustomLabelsSelectionDialogBinding labelsBinding;
|
|
private CustomAssigneesSelectionDialogBinding assigneesBinding;
|
|
private View.OnClickListener onClickListener;
|
|
private int resultLimit = Constants.resultLimitOldGiteaInstances;
|
|
private Dialog dialogLabels;
|
|
private Dialog dialogAssignees;
|
|
private String labelsSetter;
|
|
private String assigneesSetter;
|
|
private int milestoneId;
|
|
|
|
private String loginUid;
|
|
private String repoOwner;
|
|
private String repoName;
|
|
|
|
private LabelsListAdapter labelsAdapter;
|
|
private AssigneesListAdapter assigneesAdapter;
|
|
|
|
private List<Integer> labelsIds = new ArrayList<>();
|
|
private List<Labels> labelsList = new ArrayList<>();
|
|
private List<Milestones> milestonesList = new ArrayList<>();
|
|
private List<Collaborators> assigneesList = new ArrayList<>();
|
|
private List<String> assigneesListData = new ArrayList<>();
|
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
|
|
setContentView(viewBinding.getRoot());
|
|
|
|
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
|
|
|
|
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
loginUid = tinyDB.getString("loginUid");
|
|
String repoFullName = tinyDB.getString("repoFullName");
|
|
String[] parts = repoFullName.split("/");
|
|
repoOwner = parts[0];
|
|
repoName = parts[1];
|
|
|
|
// require gitea 1.12 or higher
|
|
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
|
|
|
|
resultLimit = Constants.resultLimitNewGiteaInstances;
|
|
}
|
|
|
|
viewBinding.newIssueTitle.requestFocus();
|
|
assert imm != null;
|
|
imm.showSoftInput(viewBinding.newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
|
|
|
|
viewBinding.newIssueDescription.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;
|
|
});
|
|
|
|
labelsAdapter = new LabelsListAdapter(labelsList, CreateIssueActivity.this, labelsIds);
|
|
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, CreateIssueActivity.this, assigneesListData);
|
|
|
|
initCloseListener();
|
|
viewBinding.close.setOnClickListener(onClickListener);
|
|
|
|
viewBinding.newIssueAssigneesList.setOnClickListener(this);
|
|
viewBinding.newIssueLabels.setOnClickListener(this);
|
|
viewBinding.newIssueDueDate.setOnClickListener(this);
|
|
|
|
getMilestones(repoOwner, repoName, resultLimit);
|
|
|
|
disableProcessButton();
|
|
|
|
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
|
|
|
|
viewBinding.newIssueAssigneesList.setOnClickListener(newIssueAssigneesList -> showAssignees());
|
|
|
|
if(!connToInternet) {
|
|
|
|
viewBinding.createNewIssueButton.setEnabled(false);
|
|
}
|
|
else {
|
|
|
|
viewBinding.createNewIssueButton.setOnClickListener(this);
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public void assigneesInterface(List<String> data) {
|
|
|
|
assigneesSetter = String.valueOf(data);
|
|
viewBinding.newIssueAssigneesList.setText(assigneesSetter.replace("]", "").replace("[", ""));
|
|
assigneesListData = data;
|
|
}
|
|
|
|
@Override
|
|
public void labelsInterface(List<String> data) {
|
|
|
|
labelsSetter = String.valueOf(data);
|
|
viewBinding.newIssueLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
|
|
}
|
|
|
|
@Override
|
|
public void labelsIdsInterface(List<Integer> data) {
|
|
|
|
labelsIds = data;
|
|
}
|
|
|
|
private void showAssignees() {
|
|
|
|
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
|
|
|
if (dialogAssignees.getWindow() != null) {
|
|
|
|
dialogAssignees.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
}
|
|
|
|
assigneesBinding = CustomAssigneesSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
|
|
|
|
View view = assigneesBinding.getRoot();
|
|
dialogAssignees.setContentView(view);
|
|
|
|
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss());
|
|
|
|
dialogAssignees.show();
|
|
AssigneesActions.getRepositoryAssignees(ctx, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
|
|
}
|
|
|
|
private void showLabels() {
|
|
|
|
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
|
|
|
if (dialogLabels.getWindow() != null) {
|
|
|
|
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
}
|
|
|
|
labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
|
|
|
|
View view = labelsBinding.getRoot();
|
|
dialogLabels.setContentView(view);
|
|
|
|
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss());
|
|
|
|
dialogLabels.show();
|
|
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
|
|
}
|
|
|
|
private void processNewIssue() {
|
|
|
|
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
|
|
|
|
String newIssueTitleForm = Objects.requireNonNull(viewBinding.newIssueTitle.getText()).toString();
|
|
String newIssueDescriptionForm = Objects.requireNonNull(viewBinding.newIssueDescription.getText()).toString();
|
|
String newIssueDueDateForm = Objects.requireNonNull(viewBinding.newIssueDueDate.getText()).toString();
|
|
|
|
if(!connToInternet) {
|
|
|
|
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
|
|
return;
|
|
}
|
|
|
|
if (newIssueTitleForm.equals("")) {
|
|
|
|
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
|
|
return;
|
|
}
|
|
|
|
if (newIssueDueDateForm.equals("")) {
|
|
|
|
newIssueDueDateForm = null;
|
|
}
|
|
else {
|
|
|
|
newIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(newIssueDueDateForm)));
|
|
}
|
|
|
|
disableProcessButton();
|
|
createNewIssueFunc(repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, milestoneId, newIssueTitleForm);
|
|
}
|
|
|
|
private void createNewIssueFunc(String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm) {
|
|
|
|
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, assigneesListData, labelsIds);
|
|
|
|
Call<JsonElement> call3;
|
|
|
|
call3 = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.createNewIssue(Authorization.get(ctx), repoOwner, repoName, createNewIssueJson);
|
|
|
|
call3.enqueue(new Callback<JsonElement>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
|
|
|
|
if(response2.code() == 201) {
|
|
|
|
TinyDB tinyDb = TinyDB.getInstance(appCtx);
|
|
tinyDb.putBoolean("resumeIssues", true);
|
|
|
|
Toasty.success(ctx, getString(R.string.issueCreated));
|
|
enableProcessButton();
|
|
finish();
|
|
}
|
|
else if(response2.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 {
|
|
|
|
Toasty.error(ctx, getString(R.string.issueCreatedError));
|
|
enableProcessButton();
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
|
|
|
|
Toasty.error(ctx, getString(R.string.genericServerResponseError));
|
|
enableProcessButton();
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void initCloseListener() {
|
|
|
|
onClickListener = view -> finish();
|
|
}
|
|
|
|
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
|
|
|
|
String msState = "open";
|
|
Call<List<Milestones>> call = RetrofitClient
|
|
.getApiInterface(ctx)
|
|
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
|
|
|
|
call.enqueue(new Callback<List<Milestones>>() {
|
|
|
|
@Override
|
|
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response) {
|
|
|
|
if(response.isSuccessful()) {
|
|
|
|
if(response.code() == 200) {
|
|
|
|
List<Milestones> milestonesList_ = response.body();
|
|
|
|
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
|
|
assert milestonesList_ != null;
|
|
|
|
if(milestonesList_.size() > 0) {
|
|
|
|
for (int i = 0; i < milestonesList_.size(); i++) {
|
|
|
|
//Don't translate "open" is a enum
|
|
if(milestonesList_.get(i).getState().equals("open")) {
|
|
Milestones data = new Milestones(
|
|
milestonesList_.get(i).getId(),
|
|
milestonesList_.get(i).getTitle()
|
|
);
|
|
milestonesList.add(data);
|
|
}
|
|
}
|
|
}
|
|
|
|
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(CreateIssueActivity.this,
|
|
R.layout.list_spinner_items, milestonesList);
|
|
|
|
viewBinding.newIssueMilestoneSpinner.setAdapter(adapter);
|
|
enableProcessButton();
|
|
|
|
viewBinding.newIssueMilestoneSpinner.setOnItemClickListener ((parent, view, position, id) ->
|
|
|
|
milestoneId = milestonesList.get(position).getId()
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
|
|
|
|
Toasty.error(ctx, getString(R.string.genericServerResponseError));
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onClick(View v) {
|
|
|
|
if (v == viewBinding.newIssueDueDate) {
|
|
|
|
final Calendar c = Calendar.getInstance();
|
|
int mYear = c.get(Calendar.YEAR);
|
|
final int mMonth = c.get(Calendar.MONTH);
|
|
final int mDay = c.get(Calendar.DAY_OF_MONTH);
|
|
|
|
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
|
|
(view, year, monthOfYear, dayOfMonth) -> viewBinding.newIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
|
|
datePickerDialog.show();
|
|
}
|
|
else if(v == viewBinding.createNewIssueButton) {
|
|
|
|
processNewIssue();
|
|
}
|
|
}
|
|
|
|
private void disableProcessButton() {
|
|
|
|
viewBinding.createNewIssueButton.setEnabled(false);
|
|
}
|
|
|
|
private void enableProcessButton() {
|
|
|
|
viewBinding.createNewIssueButton.setEnabled(true);
|
|
}
|
|
}
|