diff --git a/README.md b/README.md
index 7ec2af0d..79146187 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ Option 2 - Open the terminal (Linux) and navigate to the project directory. Then
- Pull requests
- Files diff for PRs
- Notifications
-- Drafts
+- Notes
- Repositories / issues list
- [& more...](https://codeberg.org/gitnex/GitNex/wiki/Features)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1ec4a7c9..b2c79cef 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -82,7 +82,11 @@
+ android:windowSoftInputMode="adjustResize"/>
+
labelsIds = new ArrayList<>();
private List assigneesListData = new ArrayList<>();
private boolean renderMd = false;
@@ -84,6 +93,11 @@ public class CreateIssueActivity extends BaseActivity
private static List attachmentsList;
private AttachmentsAdapter attachmentsAdapter;
private static final List contentUri = new ArrayList<>();
+ private CustomInsertNoteBinding customInsertNoteBinding;
+ private NotesAdapter adapter;
+ private NotesApi notesApi;
+ private List notesList;
+ public AlertDialog dialogNotes;
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -98,6 +112,8 @@ public class CreateIssueActivity extends BaseActivity
materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
+ materialAlertDialogBuilderNotes =
+ new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
repository = RepositoryContext.fromIntent(getIntent());
@@ -174,6 +190,8 @@ public class CreateIssueActivity extends BaseActivity
}
});
+ viewBinding.insertNote.setOnClickListener(insertNote -> showAllNotes());
+
getMilestones(repository.getOwner(), repository.getName(), resultLimit);
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
@@ -189,6 +207,62 @@ public class CreateIssueActivity extends BaseActivity
}
}
+ private void showAllNotes() {
+
+ notesList = new ArrayList<>();
+ notesApi = BaseApi.getInstance(ctx, NotesApi.class);
+
+ customInsertNoteBinding = CustomInsertNoteBinding.inflate(LayoutInflater.from(ctx));
+
+ View view = customInsertNoteBinding.getRoot();
+ materialAlertDialogBuilderNotes.setView(view);
+
+ customInsertNoteBinding.recyclerView.setHasFixedSize(true);
+ customInsertNoteBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
+
+ adapter = new NotesAdapter(ctx, notesList, "insert", "issue");
+
+ customInsertNoteBinding.pullToRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ notesList.clear();
+ customInsertNoteBinding.pullToRefresh.setRefreshing(
+ false);
+ customInsertNoteBinding.progressBar.setVisibility(
+ View.VISIBLE);
+ fetchNotes();
+ },
+ 250));
+
+ if (notesApi.getCount() > 0) {
+ fetchNotes();
+ dialogNotes = materialAlertDialogBuilderNotes.show();
+ } else {
+ Toasty.warning(ctx, getResources().getString(R.string.noNotes));
+ }
+ }
+
+ private void fetchNotes() {
+
+ notesApi.fetchAllNotes()
+ .observe(
+ this,
+ allNotes -> {
+ assert allNotes != null;
+ if (!allNotes.isEmpty()) {
+
+ notesList.clear();
+
+ notesList.addAll(allNotes);
+ adapter.notifyDataChanged();
+ customInsertNoteBinding.recyclerView.setAdapter(adapter);
+ }
+ customInsertNoteBinding.progressBar.setVisibility(View.GONE);
+ });
+ }
+
ActivityResultLauncher startActivityForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
diff --git a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
index 1aefe7cc..05ad2a65 100644
--- a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -14,6 +15,7 @@ import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.datepicker.MaterialDatePicker;
@@ -41,9 +43,14 @@ import org.mian.gitnex.R;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AttachmentsAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
+import org.mian.gitnex.adapters.NotesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.database.api.BaseApi;
+import org.mian.gitnex.database.api.NotesApi;
+import org.mian.gitnex.database.models.Notes;
import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.BottomSheetAttachmentsBinding;
+import org.mian.gitnex.databinding.CustomInsertNoteBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
@@ -51,6 +58,7 @@ import org.mian.gitnex.helpers.AppDatabaseSettings;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.SnackBar;
+import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.attachments.AttachmentUtils;
import org.mian.gitnex.helpers.attachments.AttachmentsModel;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
@@ -74,11 +82,17 @@ public class CreatePullRequestActivity extends BaseActivity
private RepositoryContext repository;
private LabelsListAdapter labelsAdapter;
private MaterialAlertDialogBuilder materialAlertDialogBuilder;
+ private MaterialAlertDialogBuilder materialAlertDialogBuilderNotes;
private boolean renderMd = false;
private RepositoryContext repositoryContext;
private static List attachmentsList;
private AttachmentsAdapter attachmentsAdapter;
private static final List contentUri = new ArrayList<>();
+ private CustomInsertNoteBinding customInsertNoteBinding;
+ private NotesAdapter adapter;
+ private NotesApi notesApi;
+ private List notesList;
+ public AlertDialog dialogNotes;
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -93,6 +107,8 @@ public class CreatePullRequestActivity extends BaseActivity
materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
+ materialAlertDialogBuilderNotes =
+ new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
repository = RepositoryContext.fromIntent(getIntent());
@@ -162,6 +178,8 @@ public class CreatePullRequestActivity extends BaseActivity
}
});
+ viewBinding.insertNote.setOnClickListener(insertNote -> showAllNotes());
+
getMilestones(repository.getOwner(), repository.getName(), resultLimit);
getBranches(repository.getOwner(), repository.getName());
@@ -190,6 +208,62 @@ public class CreatePullRequestActivity extends BaseActivity
}
});
+ private void showAllNotes() {
+
+ notesList = new ArrayList<>();
+ notesApi = BaseApi.getInstance(ctx, NotesApi.class);
+
+ customInsertNoteBinding = CustomInsertNoteBinding.inflate(LayoutInflater.from(ctx));
+
+ View view = customInsertNoteBinding.getRoot();
+ materialAlertDialogBuilderNotes.setView(view);
+
+ customInsertNoteBinding.recyclerView.setHasFixedSize(true);
+ customInsertNoteBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
+
+ adapter = new NotesAdapter(ctx, notesList, "insert", "pr");
+
+ customInsertNoteBinding.pullToRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ notesList.clear();
+ customInsertNoteBinding.pullToRefresh.setRefreshing(
+ false);
+ customInsertNoteBinding.progressBar.setVisibility(
+ View.VISIBLE);
+ fetchNotes();
+ },
+ 250));
+
+ if (notesApi.getCount() > 0) {
+ fetchNotes();
+ dialogNotes = materialAlertDialogBuilderNotes.show();
+ } else {
+ Toasty.warning(ctx, getResources().getString(R.string.noNotes));
+ }
+ }
+
+ private void fetchNotes() {
+
+ notesApi.fetchAllNotes()
+ .observe(
+ this,
+ allNotes -> {
+ assert allNotes != null;
+ if (!allNotes.isEmpty()) {
+
+ notesList.clear();
+
+ notesList.addAll(allNotes);
+ adapter.notifyDataChanged();
+ customInsertNoteBinding.recyclerView.setAdapter(adapter);
+ }
+ customInsertNoteBinding.progressBar.setVisibility(View.GONE);
+ });
+ }
+
public void onDestroy() {
AttachmentsAdapter.setAttachmentsReceiveListener(null);
super.onDestroy();
@@ -202,7 +276,7 @@ public class CreatePullRequestActivity extends BaseActivity
private void checkForAttachments() {
- if (contentUri.size() > 0) {
+ if (!contentUri.isEmpty()) {
BottomSheetAttachmentsBinding bottomSheetAttachmentsBinding =
BottomSheetAttachmentsBinding.inflate(getLayoutInflater());
@@ -241,7 +315,10 @@ public class CreatePullRequestActivity extends BaseActivity
RequestBody requestFile =
RequestBody.create(
- file, MediaType.parse(getContentResolver().getType(contentUri.get(i))));
+ file,
+ MediaType.parse(
+ Objects.requireNonNull(
+ getContentResolver().getType(contentUri.get(i)))));
uploadAttachments(requestFile, issueIndex, file.getName());
}
@@ -301,7 +378,7 @@ public class CreatePullRequestActivity extends BaseActivity
assignees.add("");
- if (labelsIds.size() == 0) {
+ if (labelsIds.isEmpty()) {
labelsIds.add(0);
}
@@ -383,7 +460,7 @@ public class CreatePullRequestActivity extends BaseActivity
PullRequestsFragment.resumePullRequests = true;
MainActivity.reloadRepos = true;
- if (contentUri.size() > 0) {
+ if (!contentUri.isEmpty()) {
assert response.body() != null;
processAttachments(response.body().getNumber());
contentUri.clear();
@@ -555,7 +632,7 @@ public class CreatePullRequestActivity extends BaseActivity
.title(getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
- if (milestonesList_.size() > 0) {
+ if (!milestonesList_.isEmpty()) {
for (Milestone milestone : milestonesList_) {
diff --git a/app/src/main/java/org/mian/gitnex/activities/CreateReleaseActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreateReleaseActivity.java
index 98a19715..04c381d6 100644
--- a/app/src/main/java/org/mian/gitnex/activities/CreateReleaseActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/CreateReleaseActivity.java
@@ -3,10 +3,15 @@ package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.vdurmont.emoji.EmojiParser;
import java.util.ArrayList;
import java.util.List;
@@ -17,11 +22,17 @@ import org.gitnex.tea4j.v2.models.CreateTagOption;
import org.gitnex.tea4j.v2.models.Release;
import org.gitnex.tea4j.v2.models.Tag;
import org.mian.gitnex.R;
+import org.mian.gitnex.adapters.NotesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.database.api.BaseApi;
+import org.mian.gitnex.database.api.NotesApi;
+import org.mian.gitnex.database.models.Notes;
import org.mian.gitnex.databinding.ActivityCreateReleaseBinding;
+import org.mian.gitnex.databinding.CustomInsertNoteBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.SnackBar;
+import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@@ -36,6 +47,12 @@ public class CreateReleaseActivity extends BaseActivity {
private String selectedBranch;
private RepositoryContext repository;
private boolean renderMd = false;
+ private MaterialAlertDialogBuilder materialAlertDialogBuilder;
+ private CustomInsertNoteBinding customInsertNoteBinding;
+ private NotesAdapter adapter;
+ private NotesApi notesApi;
+ private List notesList;
+ public AlertDialog dialogNotes;
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -48,6 +65,9 @@ public class CreateReleaseActivity extends BaseActivity {
repository = RepositoryContext.fromIntent(getIntent());
+ materialAlertDialogBuilder =
+ new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
+
binding.releaseContent.setOnTouchListener(
(touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
@@ -60,10 +80,7 @@ public class CreateReleaseActivity extends BaseActivity {
return false;
});
- binding.topAppBar.setNavigationOnClickListener(
- v -> {
- finish();
- });
+ binding.topAppBar.setNavigationOnClickListener(v -> finish());
binding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
@@ -103,9 +120,67 @@ public class CreateReleaseActivity extends BaseActivity {
}
});
+ binding.insertNote.setOnClickListener(insertNote -> showAllNotes());
+
getBranches(repository.getOwner(), repository.getName());
}
+ private void showAllNotes() {
+
+ notesList = new ArrayList<>();
+ notesApi = BaseApi.getInstance(ctx, NotesApi.class);
+
+ customInsertNoteBinding = CustomInsertNoteBinding.inflate(LayoutInflater.from(ctx));
+
+ View view = customInsertNoteBinding.getRoot();
+ materialAlertDialogBuilder.setView(view);
+
+ customInsertNoteBinding.recyclerView.setHasFixedSize(true);
+ customInsertNoteBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
+
+ adapter = new NotesAdapter(ctx, notesList, "insert", "release");
+
+ customInsertNoteBinding.pullToRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ notesList.clear();
+ customInsertNoteBinding.pullToRefresh.setRefreshing(
+ false);
+ customInsertNoteBinding.progressBar.setVisibility(
+ View.VISIBLE);
+ fetchNotes();
+ },
+ 250));
+
+ if (notesApi.getCount() > 0) {
+ fetchNotes();
+ dialogNotes = materialAlertDialogBuilder.show();
+ } else {
+ Toasty.warning(ctx, getResources().getString(R.string.noNotes));
+ }
+ }
+
+ private void fetchNotes() {
+
+ notesApi.fetchAllNotes()
+ .observe(
+ this,
+ allNotes -> {
+ assert allNotes != null;
+ if (!allNotes.isEmpty()) {
+
+ notesList.clear();
+
+ notesList.addAll(allNotes);
+ adapter.notifyDataChanged();
+ customInsertNoteBinding.recyclerView.setAdapter(adapter);
+ }
+ customInsertNoteBinding.progressBar.setVisibility(View.GONE);
+ });
+ }
+
private void createNewTag() {
String tagName = Objects.requireNonNull(binding.releaseTagName.getText()).toString();
@@ -114,7 +189,7 @@ public class CreateReleaseActivity extends BaseActivity {
+ "\n\n"
+ Objects.requireNonNull(binding.releaseContent.getText());
- if (tagName.equals("")) {
+ if (tagName.isEmpty()) {
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.tagNameErrorEmpty));
return;
@@ -187,13 +262,13 @@ public class CreateReleaseActivity extends BaseActivity {
boolean newReleaseType = binding.releaseType.isChecked();
boolean newReleaseDraft = binding.releaseDraft.isChecked();
- if (newReleaseTitle.equals("")) {
+ if (newReleaseTitle.isEmpty()) {
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.titleErrorEmpty));
return;
}
- if (newReleaseTagName.equals("")) {
+ if (newReleaseTagName.isEmpty()) {
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.tagNameErrorEmpty));
return;
diff --git a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java
index 34a56ebd..60070604 100644
--- a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java
@@ -11,6 +11,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -18,6 +20,8 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -57,7 +61,9 @@ import org.gitnex.tea4j.v2.models.Repository;
import org.gitnex.tea4j.v2.models.User;
import org.gitnex.tea4j.v2.models.WatchInfo;
import org.mian.gitnex.R;
+import org.mian.gitnex.actions.ActionResult;
import org.mian.gitnex.actions.AssigneesActions;
+import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.adapters.IssueCommentsAdapter;
@@ -82,6 +88,7 @@ import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
+import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.IssueContext;
import org.mian.gitnex.notifications.Notifications;
@@ -105,7 +112,7 @@ public class IssueDetailActivity extends BaseActivity
public static boolean commentPosted = false;
private final List