Implement issue templates for new issues (#1565)

closes #323

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1565
Co-authored-by: M M Arif <mmarif@swatian.com>
Co-committed-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
M M Arif
2026-01-17 08:19:17 +01:00
committed by M M Arif
parent 4ab08c7c1e
commit 0f241b0789
4 changed files with 123 additions and 3 deletions

View File

@@ -36,6 +36,7 @@ import okhttp3.RequestBody;
import org.gitnex.tea4j.v2.models.Attachment;
import org.gitnex.tea4j.v2.models.CreateIssueOption;
import org.gitnex.tea4j.v2.models.Issue;
import org.gitnex.tea4j.v2.models.IssueTemplate;
import org.gitnex.tea4j.v2.models.Label;
import org.gitnex.tea4j.v2.models.Milestone;
import org.gitnex.tea4j.v2.models.User;
@@ -198,6 +199,7 @@ public class CreateIssueActivity extends BaseActivity
viewBinding.insertNote.setOnClickListener(insertNote -> showAllNotes());
getMilestones(repository.getOwner(), repository.getName(), resultLimit);
fetchIssueTemplates();
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
@@ -674,6 +676,98 @@ public class CreateIssueActivity extends BaseActivity
});
}
private void fetchIssueTemplates() {
Call<List<IssueTemplate>> call =
RetrofitClient.getApiInterface(ctx)
.repoGetIssueTemplates(repository.getOwner(), repository.getName());
call.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<List<IssueTemplate>> call,
@NonNull retrofit2.Response<List<IssueTemplate>> response) {
if (response.isSuccessful()
&& response.body() != null
&& !response.body().isEmpty()) {
List<IssueTemplate> templates = response.body();
setupTemplateSpinner(templates);
}
}
@Override
public void onFailure(
@NonNull Call<List<IssueTemplate>> call, @NonNull Throwable t) {}
});
}
private void setupTemplateSpinner(List<IssueTemplate> templates) {
if (templates == null || templates.isEmpty()) {
viewBinding.newIssueTemplateSpinnerLayout.setVisibility(View.GONE);
return;
}
viewBinding.newIssueTemplateSpinnerLayout.setVisibility(View.VISIBLE);
List<String> templateNames = new ArrayList<>();
templateNames.add(getString(R.string.none));
for (IssueTemplate template : templates) {
templateNames.add(template.getName());
}
ArrayAdapter<String> adapter =
new ArrayAdapter<>(
CreateIssueActivity.this, R.layout.list_spinner_items, templateNames);
viewBinding.newIssueTemplateSpinner.setAdapter(adapter);
viewBinding.newIssueTemplateSpinner.setOnItemClickListener(
(parent, view, position, id) -> {
String selectedName = adapter.getItem(position);
if (selectedName == null) {
return;
}
if (selectedName.equals(getString(R.string.none))) {
viewBinding.newIssueTitle.setText("");
viewBinding.newIssueDescription.setText("");
} else {
for (IssueTemplate template : templates) {
if (template.getName().equals(selectedName)) {
applyIssueTemplate(template);
break;
}
}
}
});
}
private void applyIssueTemplate(IssueTemplate template) {
if (template == null) {
return;
}
if (template.getTitle() != null && !template.getTitle().isEmpty()) {
viewBinding.newIssueTitle.setText(template.getTitle().trim());
} else {
viewBinding.newIssueTitle.setText("");
}
String templateContent = "";
if (template.getContent() != null) {
templateContent = template.getContent();
} else if (template.getBody() != null) {
templateContent = template.getBody().toString();
}
if (!templateContent.isEmpty()) {
viewBinding.newIssueDescription.setText(templateContent.trim());
} else {
viewBinding.newIssueDescription.setText("");
}
}
@Override
public void onResume() {
super.onResume();

View File

@@ -93,7 +93,7 @@ public class CreateRepoActivity extends BaseActivity {
Objects.requireNonNull(activityCreateRepoBinding.defaultBranch.getText())
.toString();
if (!newRepoDesc.equals("")) {
if (!newRepoDesc.isEmpty()) {
if (newRepoDesc.length() > 255) {

View File

@@ -55,7 +55,32 @@
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueTemplateSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/template"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/primaryBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
android:visibility="gone">
<AutoCompleteTextView
android:id="@+id/newIssueTemplateSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:labelFor="@+id/newIssueTemplateSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueTitleLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -82,7 +107,7 @@
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/insertNote"

View File

@@ -609,6 +609,7 @@
<string name="lfs">LFS</string>
<string name="mirrors">Mirrors</string>
<string name="stars">Stars</string>
<string name="template">Template</string>
<!-- generic copy -->
<string name="exploreUsers">Explore users</string>